Borrow-fu: Incrementally currying a function, storing the curried results

I want to write a method that incrementally caches arguments to a function. I was able to do this with some Python magic yesterday, but it's not as simple in Rust. pazk/prover.py at main · thor314/pazk · GitHub

In particular, if I have:f(a,b,c,d,e)
I would like to create curried versions of that function,

f1(b,c,d,e) = f(A,b,c,d,e) // bind a=A
f2(c,d,e) = f1(B,c,d,e)
//...
f4(e) = f3(A,B,C,D,e)

I wasn't able to figure out a way do this with f defined over real arguments, as I did in python, so I've been implementing something with a vector, more like (pseudocode, length denoted in subscripts):

f1([v]_4) = f([A]+[v]_4) // bind a=A
f2([v]_3) = f1([A,B]+[v]_3)
//...
f4([v]_1) = f3([A,B,C,D]+[v]_1)

Which lives here, with an issue around borrowing.

I thooooought what I wanted was to derive Clone for my Fcache struct, so that I can solve my borrowing issue by passing ownership of a cloned value to cache_next, but I dyn Fn.. doesn't implement Clone, and I'm not sure what the work around would b.

I'm interested in any references on currying in Rust, and of course, also what Borrowing-fu I'll need to make this type safe.

Replacing Box with Rc seems to make your code work in a straightforward manner: Rust Playground

1 Like

Oh that's neat. Why can I clone an Rc wrapping Fn but not a Box? As far as I can think, dyn Fn got no more clone-able; if it were, my Box<Fn...> would have been clone-able.

Assuming you aren't ever accessing anything but the last element of the Vec anyway, you could also reclaim ownership and use e. g. an Option in place of the Vec (the Option is still there because it's easy to take a value from in order to get back ownership [1]): Rust Playground


  1. technically, you could also solve it without the Option by using mem::replace and a dummy-value ↩︎

1 Like

Rc<T> is always clonable for any type T. It doesn't duplicate the T, but instead copies the reference (and increments an internal reference counter) so both the original and the clone are a handle to the same value afterwards.

1 Like

The very point of reference counting is that you can have shared ownership of a single resource. Reference counting is used exactly for avoiding cloning the referred value. This is documented.