Functions as first-class values

It should be possible to take Roto functions and store them into variables. For example:

fn twice(x: u32) -> u32 {
    2 * x
}

fn thrice(x: u32) -> u32 {
    3 * x
}

fn main(select: bool, x: u32) -> u32 {
    let f = if select {
        twice
    } else {
        thrice
    };
    f(x)
} 

There are some limitations:

  • Function types only unify if they have the same parameters and return type
  • Methods cannot be stored in function pointers, unless they are referenced via the type (which is currently not possible).
  • There is no closure or even anonymous function syntax yet.

This should be relatively easy within Roto, but passing function pointers in and out of Roto is probably quite difficult.

It is also work towards Query DSL or API · Issue #98 · NLnetLabs/roto · GitHub .

Extension 1: Nested functions

Once we have this, it might make more sense to declare functions in other functions:

fn main(x: i32) -> i32 {
    fn plus_one(x: i32) -> i32 {
        x + 1
    }
    plus_one(x)
}

Extension 2: Anonymous functions

Once we can use functions in more places, it makes sense to provide some syntax for anonymous functions:

fn main(x: i32) -> i32 {
    let plus_one = fn(x: i32) { x + 1 };
    plus_one(x)
}

Extension 3: Closures

Finally, we might want to extend anonymous functions (when they have been implemented) so that they can capture variables from their environment.

fn main(x: i32) -> i32 {
    let plus_one = fn() { x + 1 };
    plus_one(x)
}
1 Like