[chuck-users] Passing functions as arguments

Casper Schipper casper.schipper at gmail.com
Wed Aug 26 07:22:42 EDT 2020

Hello John,

It is not really possible in normal Chuck syntax: functions are not values in Chuck and there is no function type.

However, you can simulate functions as values, by creating classes that create objects that behave like a function would.
The library LicK provides an implementation of that idea:
https://github.com/heuermh/lick/tree/master/lick/fn <https://github.com/heuermh/lick/tree/master/lick/fn>

The approach is best explained with an example I think.

// this is the Function class from LicK for functions that take one float argument.
class FloatFunction
    0.0 => float default;
    fun float evaluate(float arg0) // evaluate is abstract method applying the function to an argument. 
        return default;

// You extend it to make some function, for example, to make an addition Function object:
class Adder extends FloatFunction
    float value;
    fun void init(float arg) {
        arg => value;
    fun float evaluate(float arg0) { // here we override the evaluate method from the base class.
        return value + arg0;

// this is just a helper, to create a Adder object:
fun Adder mkAdder(float arg) {
    Adder a;
    return a;

// Now it is possible to implement map, where you can take a function object as an argument:
fun float [] map (FloatFunction f, float lst[]) {
    float result[lst.cap()];
    for (int i;i<lst.cap();i++) {
        f.evaluate(lst[i]) => result[i];
    return result;

fun void printArray(float arr[]) {
    for (int i;i<arr.cap();i++) {

// so now your transposing mapping would look something like this:
[10.,11.,12.,13] @=> float test[];

map(mkAdder(10.0),test) => printArray;
map(mkAdder(20.0),test) => printArray;

A limitation that remains with this, since there is no curying etc.., you need a lot of classes, for each function type one. So creating and defining functions like this is not very lightweight (you almost always have to extend some class :-/). No surprise I guess: this is just programming a functional programming language using an object oriented one. My personal way of getting around that limitation was to build a translator in python that takes my own (scheme-like) syntax and parses it into chuck code* to automate all that boilerplate. But that is still quite a lot work! If you are really into doing functional stuff, it may also be worthwhile to consider use a “proper" functional language (ocaml/haskell) and communicate with chuck through OSC? It depends a bit on what level you would like to use the functions (controlling parameters or audio processing itself). I probably would have done something like this now if I didn’t have a whole bunch of tools written in chuck already :-P. 

Hope this helps,

* https://github.com/casperschipper/ChucK-Tools <https://github.com/casperschipper/ChucK-Tools> & https://github.com/casperschipper/cisp <https://github.com/casperschipper/cisp>
There is some documentation in the cisp repo (sorry not very complete, this is kind of a personal toolbox).

> On 25 Aug 2020, at 22:51, John Crane <john.crane at gmail.com> wrote:
> Hi all, 
> Chuck newbie here. Is it possible to pass a function as an argument? I'd like to be able to  transform things in a functional programming manner.  As a trivial example, if I had an array of midi notes and wanted to raise them all one interval. 
>     fun int increment(int note) { 
>         note + 1; 
>     }
>     // use map to apply a function to all elements of an array
>     map ( array_of_notes, increment);
> thanks in advance,
> John
> _______________________________________________
> chuck-users mailing list
> chuck-users at lists.cs.princeton.edu
> https://lists.cs.princeton.edu/mailman/listinfo/chuck-users

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cs.princeton.edu/pipermail/chuck-users/attachments/20200826/5d5e0526/attachment.html>

More information about the chuck-users mailing list