Sign in
Log inSign up
Currying in Rust

Currying in Rust

j's photo
j
·Dec 8, 2018

This week I had a late evening hacking session with a friend of mine. We met the week before and he was complaining that rust claims to be a functional language but he's missing certain functionality he's used to in JS libs like rambda.

I was on an AI congress but I had some time so I did prepare some code for the late hacking session.

He mainly argued about 2 things

  • currying
  • function composition

Since I want to keep it short and focused I will go for currying.

For those of you who don't know what currying is.

In simple terms currying is a way to reduce arity. Arity is the fancy word for 'the amount of parameters' passed to a function. So the target of currying is to use a function that gets a parameter to return a function (lambda) that contains the parameter from before.

so this would be an add function without currying

fn main() {
    let r = add(1, 2);
    println!("{}", r);
}

fn add(x: i32, y: i32) -> i32 {
  x + y
}

during the code we write we find out that x actually rarely changes and we would have to write the same code over and over again. Since we're lazy we want to reduce the amount of code we write and see.

fn main() {
    let c_add = curry_add(1);
    let r1 = c_add(4); 
    let r2 = c_add(5);
    println!("{}", r1); // 5
    println!("{}", r2); // 6
}

fn curry_add(n: i32) -> impl Fn(i32) -> i32 {
  move |x| x + n
}

For those of you who will now want to start the 'in this case you can use a variable for the same purpose' threads ... I just try to keep the examples simple because I want to transport the core idea.

Currying is a way to produce higher order functions that contain some context that in turn can be applied to all passed in parameters.

I will stop here, we did a lot more in the session where we got into lifetime issues and I don't want to add the confusing parts of boxing, lifetime annotations and generics.