This post was originally published on monades.roperzh.com
Pony is an emerging programming language which is described by its authors as "an open-source, object-oriented, actor-model, capabilities-secure, high-performance programming language."
Wording aside, this article focuses on the most interesting aspects of the language itself and how the code looks like.
Pony inhabits in the reigns of compiled languages, when executing the
ponyc command (which is part of the Pony installation) the compiler creates an executable with the same name of the current folder.
$ cd myprogram $ ponyc $ ./myprogram
A lot of the guarantees that Pony offers (no exceptions at runtime, secure capabilities and more) are backed up by its type system. If you miss a type or assign a value to a variable of a different type, the compiler complains and stops the compilation.
The syntax to denote a type is
class Hello // name is a variable of type String let name: String // age is a variable of type U64 let age: U64 // the argument name' is a variable of type string new create(name': String) => name = name'
However, in certain scenarios, types are inferred by the compiler. Here, for example, the type of the
hello variable can be safely omitted.
let hello = Hello("Seneca")
Pony is object-oriented and exposes it with classes. A class is declared with the keyword
class, and can have:
- One or many constructors differentiated by name
Unlike many other OOP languages, Pony doesn't have the concept of inheritance, instead it embraces traits and interfaces.
class Book // Fields of a given class are defined // like this. // - `var` fields can be asigned multiple times // - `let` fields can only be assigned once in the constructor. // - fields starting with underscore are private let author: String var _editions: U32 new create(author': String, editions': U32) => author = author' _editions = editions' // A class can have functions fun get_author(): String => author fun get_editions(): U32 => _editions // To set values, is necessary to mark // the function as `ref` fun ref set_editions(to: U32) => _editions = to
Pony embraces the Actor Model and supports it out of the box. If you haven't heard of it, and you're interested, feel free to check out Get to Know the Actor Model.
In the Pony world, actors are similar to classes, with the only difference that they are asynchronous entities. Instead of functions an actor has behaviors; when called, the body of a behavior is not executed syncronously, instead, it will be executed at some indeterminate time in the future.
use "promises" actor Writer // As with classes, you can define fields let name: String // And constructors too! new create(name': String) => name = name' // Instead of functions, an Actor has behaviors be get_name(promise: Promise[String]) => promise(name)
Hence the asynchronous nature of actors, Pony also comes with primitives to enable asynchronous communication through
Promise represents a value that will be available at a later time.
Promises are either fulfilled with a value or rejected. If you're interested in the details of Pony promises, there's an excellent blog post by Kevin Hoffman on the subject.
// Create a new Actor let writer = Writer("Italo Calvino") // Create a new promise let promise = Promise[String] // Invoke the Actor behavior, providing a // promise to be fulfilled writer.get_name(promise) // Print the value of the promise when fullfilled // using a partial application of `env.out.print` promise.next[None](env.out~print())
Pony comes with the
PonyTest package which provides a simple unit testing framework: each unit test is a class, with a single test function, and by default, all tests run concurrently.
use "ponytest" actor Main is TestList new create(env: Env) => PonyTest(env, this) fun tag tests(test: PonyTest) => test(_TestAdd) class iso _TestAdd is UnitTest fun name():String => "addition" fun apply(h: TestHelper) => h.assert_eq[U32](4, 2 + 2)
- You integrate Pony with C through the Foreign Function Interface (FFI)
- Division by zero is allowed, and results in zero
a = bis an expression that returns the old value of
- ~5 years of life, first commit at Nov 9, 2012
- 4,549 commits
- 46 releases
- 104 contributors
- 2,672 GitHub stars
76 questions tagged with
note: this numbers date of 10/31/2017, they become more and more invalid as time goes on; moreover, they don't represent anything significant and are included only for fun.