Bluish Coder

Programming Languages, Martials Arts and Computers. The Weblog of Chris Double.


2016-03-15

Closures in Pony

Note 2017-08-01: Recent releases of Pony have changed syntax for lambda calls and partial function calls. This post has been updated to work with these changes as of Pony 0.16.1.

The Pony programming language has support for closures but the documentation hasn't caught up with changes to the implementation. This post describes some of the features of Pony closures with examples. These examples require the latest version of Pony from the github repository. I used commit e4f6f91d.

Lambda

Closures are functions combined with an environment mapping names to values. Pony has a {...} syntax that can be used to create them. It's possible to create a function that captures from the lexical scope and to create a function with no capturing at all.

The following example shows using a lambda that does not capture anything (note that this is an artificial example - the List type already has various mapping and fold functions on it):

use "collections"

actor Main
  new create(env:Env) =>
    let l = List[U32]
    l.push(10)
    l.push(20)
    l.push(30)
    l.push(40)
    let r = reduce(l, 0, {(a:U32,b:U32): U32 => a + b})
    env.out.print("Result: " + r.string())

  fun reduce(l: List[U32], acc: U32, f: {(U32, U32): U32} val): U32 =>
    try
      let acc' = f(acc, l.shift()?)
      reduce(l, acc', f)
    else
      acc
    end

The reduce function takes an anonymous function as a parameter, named f. This is is defined as {(U32, U32): U32}. This syntax means that it must take two U32 arguments and returns a U32. A U32 is a 32-bit unsigned integer.

The val is a reference capability annotation. It states that f is an immutable value. Since nothing inside f can be mutated it is safe for f to be shared with other actors. Lambda functions that do not close over other variables default to val as they cannot change anything outside of the function. We need to explicitly annotate the val as {...} declarations default to ref. A compile error would result without it due to passing a val object to a ref parameter.

Compiling and running produces the result 100 as expected:

$ ponyc example
$ ...
$ ./example1
  Result: 100

Lambda with environment

The following example closes over the env variable so that it can be accessed within the lambda to print the String contained in the List:

use "collections"

actor Main
  new create(env:Env) =>
    let l = List[String]
    l.push("hello")
    l.push("world")
    for_each(l, {(s:String)(env) => env.out.print(s)})

  fun for_each(l: List[String], f: {(String)}) =>
    try
      f(l.shift()?)
      for_each(l, f)
    end

Notice that the lambda has an additional set of parameters, the (env). This is an argument list of the variables that are being closed over. Variables listed there can be accessed from the body of the lambda. Pony requires you to be explicit about what gets captured vs many other languages that implicitly capture variables in scope. Variables can be renamed in this parameter list using the following syntax:

for_each(l, {(s:String)(myenv=env) => myenv.out.print(s)})

The lambda here returns None which is the default so it is left off the declaration {(String)}. This declaration requires a function that takes a single String argument and returns None. The return value is also left off the actual lambda expression. No reference capability annotations are required here as {...} defaults to ref and a lambda that closes over variables also defaults to ref.

Lambda modifying closed variables

A modification of the above example might be to keep a count of each time the lambda is called and display the count:

actor Main
  new create(env:Env) =>
    let l = List[String]
    l.push("hello")
    l.push("world")
    var count = U32(0)
    for_each(l, {ref(s:String)(env,count) =>
                    env.out.print(s)
                    count = count + 1})
    // Displays '0' as the count
    env.out.print("Count: " + count.string())

fun for_each(l: List[String], f: {ref(String)}) =>
  try
    f(l.shift()?)
    for_each(l, f)
  end

The main thing to note here is that both the lambda definition and the declaration have a ref prefixed to the argument list. This signifies a lambda that might mutate itself when called. The effect of this is that within the body of the lambda the receiver of method calls and field access (ie. the this of the lambda object) is a ref vs the default of box. A box receiver won't allow ref functions to be called and mutating requires a ref receiver.

There is an issue with this example as noted by the comment. The final count is displayed as zero. The assignment of count within the lambda changes the count field within the lambda object. The count within the lambda increments and could be displayed showing the increasing values. The count outside of this does not. There is no reference or pointer to the closed over variable. Indirection can be used to do this by using a one element array:

var count : Array[U32] = Array[U32].init(0, 1)
for_each(l, {ref(s:String)(env,count) =>
              try
                env.out.print(s)
                count(0)? = count(0)? + 1
              end})
try
  env.out.print("Count: " + count(0)?.string())
end

The array access is wrapped with try as it is a partial function and can fail. Another approach could be to move the act of counting into an Actor:

use "collections"

actor Counter
  var n: U32 = 0

  be increment() =>
    n = n + 1

  be print(env:Env) =>
    env.out.print("Count: " + n.string())

actor Main
  new create(env:Env) =>
    let l = List[String]
    l.push("hello")
    l.push("world")
    let counter = Counter
    for_each(l, {(s:String)(env,counter) =>
                  env.out.print(s)
                  counter.increment()})
    counter.print(env)

  fun for_each(l: List[String], f: {(String)}) =>
    try
      f(l.shift()?)
      for_each(l, f)
    end

Actors have the tag reference capability and are easier to pass around to other objects, including lambda.

The example here is contrived in that it can be done without modifying a captured variable. Sylvan produced the following approach, using the methods in the collections package:

use "collections"

actor Main
  new create(env:Env) =>
    let l = List[String]
    l.push("hello")
    l.push("world")

    let count = l.fold[U32](
      {(x: U32, s: String)(env): U32 =>
        env.out.print(s)
        x + 1}, 0)

    env.out.print("Count: " + count.string())

Object Literals

Object literals are a way to create objects inline without having to name a class or actor. They look like:

object
  let x = 10
  fun foo() =>
    ...do something...
end

Lambda's are actually syntactic sugar on top of object literals. A lambda expansion looks like:

// Lambda
{(s:String)(env) => env.out.print(s)}

// Expands to:
object
  var env:Env = env
  fun apply(s:String) =>
    env.out.print(s)
end

The apply method of an object is called when the () function call syntax is used. Keeping this syntactic transformation in mind can help solve errors that occur when using lambda. The example earlier where the count total didn't account for the increments in the lambda becomes obvious here. The transformation would be:

var count = U32(0)
for_each(l, object
              var env:Env = env
              var count:U32 = count
              fun ref apply(s:String) =>
                env.out.print(s)
                count = count + 1
            end)
env.out.print("Count: " + count.string())

Note the ref annotation in the apply method. This is what the {ref(...)} syntax results in. Without the ref in the {} syntax the syntactic expansion is fun apply(...). The default reference capability for fun in objects is box.

The object literal expansion helps show the difference between {(string)} ref and {ref(String))}. The first requires an object with the given reference capability to match the type. Although the object is a ref, the apply method is the default, a box. This means it cannot modify any fields in the object. In the case of a lambda it won't be able to modify the captured variables:

object ref
  fun apply(...)
end

To match the second type definition it requires an object where the apply method itself has the ref capability. This allows apply to modify fields of the object:

object
  fun ref apply(...)
end

Partial Application

Related to lambda is partial application. It allows supplying some arguments to a function (or constructor or behaviour) and returns something that allows supplying the other arguments later.

In cases where you would use a lambda to return a function that sets the value of some arguments you can use partial application instead. The following example creates a lambda that adds five to another number:

actor Main
  new create(env:Env) =>
    let add5 = {(a:U32): U32 => 5 + a}
    env.out.print(add5(10).string())
    env.out.print(add5(20).string())

With partial application this becomes:

actor Main
  new create(env:Env) =>
    let add5 = U32(5)~add()
    env.out.print(add5(10).string())
    env.out.print(add5(20).string())

The use of + is an alias for the add method on an object. In the example above the ~ operator represents partial application. We are binding the receiver of the add method to be the 32-bit unsigned value 5. The resulting object can be called with the remaining arguments.

Partial application allows binding any arguments, by position or by name. The tutorial goes into a lot of detail.

Accumulator Generator

Paul Graham has an accumulator generator problem with examples in various languages. The problem is defined as:

Write a function foo that takes a number n and returns a function that takes a number i, and returns n incremented by i.

A Pony implementation, using closures, could be:

actor Main
  fun foo(n:U32): {ref(U32): U32} =>
    var s: Array[U32] = Array[U32].init(n, 1)
    {ref(i:U32)(s): U32 =>
      try
        s(0)? = s(0)? + i
        s(0)?
      else
        0
      end}

  new create(env:Env) =>
    var f = foo(5)
    env.out.print(f(10).string())
    env.out.print(f(20).string())

This uses the one element array trick to enable modifying the captured variable due to the requirement that the number n is incremented. It works only for U32 rather than any number which is also part of the problem definition. Pony has generics which would allow solving this but I'll leave that as an exercise or a future post.

Further reading

Some links to documentation and posts about lambda and reference capabilities to dive into more detail:

Tags: pony 

2015-12-17

Cross compile Pony programs for Android

Support for compiling Pony programs on ARM and 32-bit x86 landed recently. This allows compiling and running Pony on Raspberry Pi and other ARM devices. I was curious if it would be possible to compile Pony programs to run on Android and this post outlines how I got a "Hello World" example working.

The Pony compiler, ponyc, does not currently support cross compilation. It uses the C pre-processor to generate code for the platform it is running on. This has hardcoded assumptions for byte size (32 vs 64 bit) and processor support (ARM vs x86). Note that this is a proof of concept and hacks the compiler and runtime source to get things working. From this I hope to learn more elegant ways of supporting cross compiling.

Ponyc Android Cross Compiler

The first step was to build a version of ponyc that would generate Android compatible ARM code without any host platform specific code being included. I built ponyc for 32-bit x86, modified to not include any x86 specific code generation and to allow selecting the non-native LLVM backends. This ensures that the hard coded assumptions for the 32-bit size matches my target, 32-bit Android.

The changes for this are in the android_ponyc_cross branch of my github repository. The changes were:

  1. Modify the Makefile to use 32-bit flags to the compiler.
  2. Add some LLVM initialization to allow selection of non-native backends so ARM can be generated on x86 hosts.
  3. Comment out some PLATFORM_IS_X86 preprocessor statements to prevent x86 specific code being generated.

For a real cross compiler these would be changed to be runtime selectable in some way. For the proof of concept it suffices to create a hardcoded compiler specific for this example.

For me it was necessary to build a version of LLVM for 32-bit as I'm on a 64-bit host. This was done by doing the following:

$ sudo apt-get install libicu-dev:i386 libncurses5-dev:i386 libxml2-dev:i386
$ tar xvf /tmp/llvm-3.6.2.src.tar.xz
$ cd llvm-3.6.2.src/tools
$ tar xvf /tmp/cfe-3.6.2.src.tar.xz
$ mv cfe-3.6.2.src clang
$ cd ..
$ mkdir build
$ cd build
$ cmake -DLLVM_BUILD_32_BITS=ON -DCMAKE_INSTALL_PREFIX=/tmp/llvm ..      
$ make
$ make install

Building the modified ponyc used these steps:

$ git clone -b android_ponyc_cross https://github.com/doublec/ponyc android_ponyc_cross
$ cd android_ponyc_cross
$ LLVM_CONFIG=/tmp/llvm/bin/llvm-config CXX="g++ -m32" make config=release ponyc

This generates a ponyc executable in the build/release directory.

Android compatible Pony runtime

An Android compatible libponyrt library is needed to link. The changes to build this are on the android_libponyrt branch. This must be built using an Android NDK standalone toolkit. A compatible standalone toolkit can be created with the following run from the NDK root directory:

$ ./build/tools/make-standalone-toolchain.sh --arch=arm \
     --platform=android-21 --install-dir=/tmp/stk21

Add the resulting installation directory to the PATH:

$ export PATH=/tmp/stk21/bin:$PATH

Make sure a recent ponyc compiler is on the PATH. This should not be the cross compiler built previously but a ponyc compiler for the host platform. Build the runtime library with:

$ git clone -b android_libponyrt https://github.com/doublec/ponyc android_libponyrt
$ cd android_libponyrt
$ CC=arm-linux-androideabi-gcc make config=release libponyrt

The resulting library is in the directory build/release/libponyrt.a.

Compiling to Android

With the above tasks complete it's now possible to build an Android compatible binary. I tested with a "Hello World" example:

actor Main
  new create(env:Env) =>
    env.out.print("Hello Android")

With that in a main.pony file in a hello directory, build with:

$ /tmp/android_ponyc_cross/build/release/ponyc --triple arm-linux-androideabi -rir hello
...ignore warnings about core-avx2 feature here...
$ llvm-as hello.ll
$ llc -mtriple=arm-linux-androideabi hello.bc -o hello.o -filetype=obj
$ arm-linux-androideabi-gcc -fPIE -pie hello.o -o hello1 -L/tmp/android_libponyrt/build/release/ -lponyrt 

The first command instructs our cross compiler to generate code for Android and to only produce the LLVM assembly listing. This is compiled to bytecode with llvm-as and then to an object file with llc. The Android version of gcc is used to link with the Android version of libponyrt that was created earlier. The hello binary that is produced can be copied to an Android device (I used a Note 3 running Lollipop) and run:

$ adb push hello1 /data/local/tmp/
$ adb shell
$ cd /data/local/tmp
$ ./hello1
Hello Android

Conclusion

I haven't tested any other features running on Android yet but this is a promising start. Using the Pony FFI and JNI it is hopefluly possible to write native Android applications.

The steps I used for getting ponyc to generate LLVM instructions and using the LLVM tools to compile it were obtained from a gist by Darach Ennis. Similar steps would probably work on other LLVM compatible platforms.

Tags: pony 

2015-12-16

C linkable libraries with Pony

Note 2017-08-01: Recent releases of Pony have changed some of the details of interacting with C. This post has been updated to work with these changes as of Pony 0.16.1.

My quick look at Pony post covered how to use the FFI to call C code from a Pony program. It's also possible to compile Pony code to a C library that can be linked into a C program. This allows integrating Pony into existing C projects without having to convert the C project into a library to be called by Pony.

I've put a small example of how to do this on github at https://github.com/doublec/pony-clib-example.

Pony has a special type of actor that will result in a C compatible interface being generated. The syntax for this is actor@. The example in the project is:

actor@ Foo
  new create() =>
    None

  be hi() =>
    @printf[I32]("Hi\n".cstring())

This creates a C compatible actor called Foo. It has a constructor create and a behaviour hi. The constructor does nothing and only exists in the example to show how to call it from C. The hi behaviour calls the C function printf using the Pony FFI. With a file main.pony containing this code in a clib directory it can be built with:

$ ponyc -l clib
Building builtin -> packages/builtin
Building clib -> clib
Generating
Optimising
Writing ./clib.o
Archiving ./libclib.a

The -l switch to ponyc results in a static library being built instead of an executable. A libclib.a is generated containing the compiled Pony code. A clib.h is also generated containing the C function declarations for creating and interacting with any actor@ instances. For the Foo actor this looks like:

typedef struct Foo Foo;
Foo* Foo_Alloc();
None* Foo_tag_hi_o__send(Foo* self);
Foo* Foo_tag_create_o__send(Foo* self);

Pony has a runtime that needs to be initialized from C and a scheduler that needs to be started. The definitions for these runtime functions can be found in the ponyc source in libponyrt/pony.h. This needs to be included by the C program. A basic C driver for the example project is:

#include <stdio.h>
#include "clib.h"
#include "pony.h"

int main(int argc, char** argv) {
  pony_init(argc, argv);

  Foo* x = Foo_Alloc();
  Foo_tag_hi_o__send(x);
  Foo_tag_create_o__send(x);

  pony_start(true, true);
  return 0;
}

This sould be compiled and linked against libclib.a and libponyrt.a:

export PONYRT_INCLUDE=/path/to/ponyc/src/libponyrt/
export PONYRT_COMMON=/path/to/ponyc/src/common
export PONYRT_LIB=/path/to/ponyc/build/release/libponyrt.a

gcc -o test -I. -I $(PONYRT_INCLUDE) -I $(PONYRT_COMMON) \
    -g -rdynamic -mcx16 test.c libclib.a $(PONYRT_LIB) -lpthread -ldl

The C code needs to call pony_init to initialize the Pony runtime. It gets passed the standard C argc and argv arguments that main receives so it can handle any Pony runtime specific switches. After this any Pony actors can be allocated and methods or behaviours called on them. The order for actor creation is to call the _Alloc function to allocate the memory for the actor and then the constructor method. Pony names the constructor method based on the name in the Pony code with __send appended.

Actors are asynchronous so just like in Pony code behaviours aren't run immediately. They are queued for execution and will run when the scheduler is started. This is what pony_start does. The arguments passed to pony_start are a boolean indicating whether to block until all Pony actors have completed (by passing a false value) or to return immediately (by passing a true value). If the latter is done then the scheduler runs asynchronously. It can be stopped with a later call to pony_stop. The second parameter indicates whether to initialize Pony specific parts of the runtime (sockets and serialization). It's possible to continue calling Pony functions after the pony_start and before pony_stop. For example:

pony_init(argc, argv);

Foo* x = Foo_Alloc();
Foo_tag_hi_o__send(x);
Foo_tag_create_o__send(x);

pony_start(true, true);

Foo* y = Foo_Alloc();
Foo_tag_hi_o__send(y);
Foo_tag_create_o__send(y);

pony_stop();

In this snippet another actor is created after pony_start and behaviours are called on it. These are queued and run as expected. pony_stop blocks until all Pony actors have completed.

There are other Pony runtime functions in pony.h that allow allocating memory on the current actor heap, unscheduling an actor so that no behaviours will be run until rescheduled, making a C thread 'become' an actor so it can call Pony runtime functions, poll for messages on an unscheduled actor, etc. It's possible to allocate an actor, unschedule it, and then use a C thread to handle its message queue using pony_become. When you aren't handling messages to the unscheduled actor you can call functions to it from C with no race conditions.

None of this is currently documented and it will probably change as usage develops. In the meantime it's a useful feature for using Pony functionality in existing applications.

Tags: pony 

2015-11-19

Exporting Self objects to source files using the Transporter

Following on from my previous video on using the Self GUI to create objects, I've done another that demonstrates how to export the objects to Self source files where they can be managed with a version control system and shared with other developers.

The video is available as self_transporter.webm, self_transporter.mp4 or on YouTube.

More information on using the transporter tool can be obtained from:

Tags: self 

2015-11-18

Demo of programming in Self

The Self programming language has a GUI environment which can be a bit intimidating to people new to the system. The Self Handbook covers it but it's difficult to convey usage with text and static images.

I've created a video that demonstrates how to develop in Self using the GUI to create a 'bank account' object and manipulate it. The idea of this was based on a discussion on the Self issue tracker about tutorials for Self.

The video is available as self_bankaccount.webm, self_bankaccount.mp4 or on YouTube.

Tags: self 


This site is accessable over tor as hidden service 6vp5u25g4izec5c37wv52skvecikld6kysvsivnl6sdg6q7wy25lixad.onion, or Freenet using key:
USK@1ORdIvjL2H1bZblJcP8hu2LjjKtVB-rVzp8mLty~5N4,8hL85otZBbq0geDsSKkBK4sKESL2SrNVecFZz9NxGVQ,AQACAAE/bluishcoder/-61/


Tags

Archives
Links