How to create a `FnOnce` function - functional-programming

I am trying to create a function that is only a FnOnce.
The following snippet of code do not work:
// Attempt 1
// Error doesn't have a size known at compile-time
let f: FnOnce() -> () = || println!("Hello");
// Attempt 2
fn g<T: FnOnce() -> ()>(c: T) -> (FnOnce() -> ()) {
c
}
// Error: doesn't have a size known at compile-time
let f = g(|| println!("Hello"));
// Attempt 3
// Error: cast to unsized type
let f = (|| println!("Hello")) as (FnOnce() -> ());

FnOnce is a trait for closures which can only be called once, typically because the captured values are moved into the closure, and they are consumed during the call. For example, we can capture a value and move it out as a return value:
fn delay<A: 'static>(a: A) -> Box<dyn FnOnce() -> A> {
Box::new(move || a)
}
fn main() {
let a = "hello".to_string();
let f = delay(a);
println!("{}", f());
}
Note that the move keyword is not strictly necessary. The compiler sees that a needs to be moved into the closure, in order to be returned as a value and moved out.

Related

Using lift with the Either or the Maybe monad

When I read about the concept of lift, it's implemented like this (in Javascript)
const liftA2 = f => (a, b) => b.ap(a.map(f));
I realise there is a case in which liftA2 will produce an error: when b is a Right/Just and a is a Left/Nothing, because mapping a Left/Nothing will do nothing to the value when we would need it to become a partially applied function.
When a and b are both a Left it doesn't blow up but of course the value of the returned Left is going to be the value of b which I suppose could be a problem depending on what you expect.
Is it a thing to lift a function to be used with these types? Should I systematically guard against these cases explicitly before using such a function? Is the above implementation correct/complete?
You will find more details about the issue bellow
Let us define the function to lift
const add = a => b => a + b;
In the case of a basic Wrapper implementing of, ap and map, we can follow what is happening
class Wrapper {
constructor(value) {
this.value = value;
}
static of(value) { return new Wrapper(value); }
map(f) { return Wrapper.of(f(this.value)); }
ap(a) { return this.map(a.value); }
}
const a = Wrapper.of(1);
const b = Wrapper.of(2);
// liftA2
const tmp = a.map(add); // Wrapper { λ }
b.ap(tmp); // Wrapper { 3 }
But the thing with Either or Maybe is that they have a Left/Nothing case where map and ap are intended to do nothing special
class Left {
constructor(value) {
this.value = value;
}
static of(value) { return new Left(value); }
map(f) { return this; }
ap(a) { return this; }
}
class Right{
constructor(value) {
this.value = value;
}
static of(value) { return new Right(value); }
map(f) { return Right.of(f(this.value)); }
ap(a) { return this.map(a.value); }
}
const a = Left.of(1);
const b = Right.of(2);
// liftA2
const tmp = a.map(add); // Left { 1 }
b.ap(tmp); // Error because tmp's value is not a function
My Javascript is a little basic (I don't use it much). But I think, as has been pointed out in the comments, your implementation of ap is not doing what you want it to.
First, take a look at this answer to a similar question about what lifting is in the first place. It is supposed to take a function of n parameters and put it into the context of a given Functor/Monad where each parameter is contained in that Functor/Monad.
In other words, if f: 'a -> 'b -> 'c (a function that takes two parameters of types 'a and 'b and returns a result of type 'c) then we could use a lift2 where:
lift2:: ('a -> 'b -> 'c) -> (M['a] -> M['b] -> M['c])
which would turn f into a function that takes an M[a] and an M[b] and returns an M[c] (where M in this case is your Either or Maybe).
Since I am more familiar with F# I will use that as an example here. If I was to implement lift2 for Option in F# (equivalent to Maybe) I would do it something like this:
let lift2 (f: 'a -> 'b -> 'c) : ('a option -> 'b option -> 'c option) =
let f2 ao bo =
match ao, bo with
| Some a, Some b -> Some(f a b)
| _, _ -> None
f2
You see here that I match on both input types. Both have to be a Some to return a Some value. Otherwise I just return a None. In the case of a Result (equivalent to an Either) I would have to determine which way to bias the match. It could go either way in terms of which Left/Error value to return.
Using the above code in FSI I get the following:
> let f' = lift2 f;;
val f' : (int option -> int option -> int option)
> f' (Some(2)) (Some(3));;
val it : int option = Some 5
> f' (Some(2)) None;;
val it : int option = None
> f' None (Some(3));;
val it : int option = None

Passing references to recursive calls

Am I right in assuming that a recursive function that receives an iterator is not expressible in safe Rust? Something like this:
fn rec_fn<'a, I: Iterator<Item = &'a MyItem>>(it: &mut I) -> Foo {
while let Some(x) = it.next() {
if some_condition(x) {
let foo = rec_fn(&mut it);
// use foo
}
// …
}
// …
}
I can't pass the mutable it reference to another call of the same fn because I'm still using it to loop over it. Is there a way to express this, or will I have to unroll the recursion and do it iteratively?

Is it possible to have a closure call itself in Rust? [duplicate]

This is a very simple example, but how would I do something similar to:
let fact = |x: u32| {
match x {
0 => 1,
_ => x * fact(x - 1),
}
};
I know that this specific example can be easily done with iteration, but I'm wondering if it's possible to make a recursive function in Rust for more complicated things (such as traversing trees) or if I'm required to use my own stack instead.
There are a few ways to do this.
You can put closures into a struct and pass this struct to the closure. You can even define structs inline in a function:
fn main() {
struct Fact<'s> { f: &'s dyn Fn(&Fact, u32) -> u32 }
let fact = Fact {
f: &|fact, x| if x == 0 {1} else {x * (fact.f)(fact, x - 1)}
};
println!("{}", (fact.f)(&fact, 5));
}
This gets around the problem of having an infinite type (a function that takes itself as an argument) and the problem that fact isn't yet defined inside the closure itself when one writes let fact = |x| {...} and so one can't refer to it there.
Another option is to just write a recursive function as a fn item, which can also be defined inline in a function:
fn main() {
fn fact(x: u32) -> u32 { if x == 0 {1} else {x * fact(x - 1)} }
println!("{}", fact(5));
}
This works fine if you don't need to capture anything from the environment.
One more option is to use the fn item solution but explicitly pass the args/environment you want.
fn main() {
struct FactEnv { base_case: u32 }
fn fact(env: &FactEnv, x: u32) -> u32 {
if x == 0 {env.base_case} else {x * fact(env, x - 1)}
}
let env = FactEnv { base_case: 1 };
println!("{}", fact(&env, 5));
}
All of these work with Rust 1.17 and have probably worked since version 0.6. The fn's defined inside fns are no different to those defined at the top level, except they are only accessible within the fn they are defined inside.
As of Rust 1.62 (July 2022), there's still no direct way to recurse in a closure. As the other answers have pointed out, you need at least a bit of indirection, like passing the closure to itself as an argument, or moving it into a cell after creating it. These things can work, but in my opinion they're kind of gross, and they're definitely hard for Rust beginners to follow. If you want to use recursion but you have to have a closure, for example because you need something that implements FnOnce() to use with thread::spawn, then I think the cleanest approach is to use a regular fn function for the recursive part and to wrap it in a non-recursive closure that captures the environment. Here's an example:
let x = 5;
let fact = || {
fn helper(arg: u64) -> u64 {
match arg {
0 => 1,
_ => arg * helper(arg - 1),
}
}
helper(x)
};
assert_eq!(120, fact());
Here's a really ugly and verbose solution I came up with:
use std::{
cell::RefCell,
rc::{Rc, Weak},
};
fn main() {
let weak_holder: Rc<RefCell<Weak<dyn Fn(u32) -> u32>>> =
Rc::new(RefCell::new(Weak::<fn(u32) -> u32>::new()));
let weak_holder2 = weak_holder.clone();
let fact: Rc<dyn Fn(u32) -> u32> = Rc::new(move |x| {
let fact = weak_holder2.borrow().upgrade().unwrap();
if x == 0 {
1
} else {
x * fact(x - 1)
}
});
weak_holder.replace(Rc::downgrade(&fact));
println!("{}", fact(5)); // prints "120"
println!("{}", fact(6)); // prints "720"
}
The advantages of this are that you call the function with the expected signature (no extra arguments needed), it's a closure that can capture variables (by move), it doesn't require defining any new structs, and the closure can be returned from the function or otherwise stored in a place that outlives the scope where it was created (as an Rc<Fn...>) and it still works.
Closure is just a struct with additional contexts. Therefore, you can do this to achieve recursion (suppose you want to do factorial with recursive mutable sum):
#[derive(Default)]
struct Fact {
ans: i32,
}
impl Fact {
fn call(&mut self, n: i32) -> i32 {
if n == 0 {
self.ans = 1;
return 1;
}
self.call(n - 1);
self.ans *= n;
self.ans
}
}
To use this struct, just:
let mut fact = Fact::default();
let ans = fact.call(5);

Weird borrowing check failure

I have roughly the following code:
let val = util::replace(&mut self.some_field[i], self.some_method());
It fails with the following message:
unrelated.rs:61:65: 61:70 error: cannot borrow `*self` as immutable because it is also borrowed as mutable
unrelated.rs:61 let val = util::replace(&mut self.some_field[i], self.some_method());
^~~~~
unrelated.rs:61:36: 61:62 note: second borrow of `*self` occurs here
unrelated.rs:61 let val = util::replace(&mut self.some_field[i], self.some_method());
^~~~~~~~~~~~~~~~~~~~~~~
I can fix this by the following code:
let temp = self.some_method();
let val = util::replace(&mut self.some_field[i], temp);
But why does it fail? The scopes in which mutable and immutable pointers are taken are distinct, they are different expressions. It looks like kind of bug to me, but I just want to make sure that I'm not missing something here.
By introducing temp you've changed computation order: you first computed some_method(), then released self, and then got a mutable reference to some_field of self.
Rust does not allow holding mutable reference along with any other reference (mutable or immutable). See simpler example:
struct Foo {
a: int
}
impl Foo {
fn ff(&self) -> int { 1 }
}
fn fff(a: int, foo: &mut int) { }
fn ggg(foo: &mut int, a: int) { }
fn main() {
let mut foo = Foo { a: 0 };
fff(foo.ff(), &mut foo.a); // this call is valid
ggg(&mut foo.a, foo.ff()); // this is not
}
This is a bug: #6268.
It is because the borrow checker doesn't account for nested method calls properly yet: the nested calls should be equivalent to the code with the temporary (and thus, should be valid).

Is it possible to make a recursive closure in Rust?

This is a very simple example, but how would I do something similar to:
let fact = |x: u32| {
match x {
0 => 1,
_ => x * fact(x - 1),
}
};
I know that this specific example can be easily done with iteration, but I'm wondering if it's possible to make a recursive function in Rust for more complicated things (such as traversing trees) or if I'm required to use my own stack instead.
There are a few ways to do this.
You can put closures into a struct and pass this struct to the closure. You can even define structs inline in a function:
fn main() {
struct Fact<'s> { f: &'s dyn Fn(&Fact, u32) -> u32 }
let fact = Fact {
f: &|fact, x| if x == 0 {1} else {x * (fact.f)(fact, x - 1)}
};
println!("{}", (fact.f)(&fact, 5));
}
This gets around the problem of having an infinite type (a function that takes itself as an argument) and the problem that fact isn't yet defined inside the closure itself when one writes let fact = |x| {...} and so one can't refer to it there.
Another option is to just write a recursive function as a fn item, which can also be defined inline in a function:
fn main() {
fn fact(x: u32) -> u32 { if x == 0 {1} else {x * fact(x - 1)} }
println!("{}", fact(5));
}
This works fine if you don't need to capture anything from the environment.
One more option is to use the fn item solution but explicitly pass the args/environment you want.
fn main() {
struct FactEnv { base_case: u32 }
fn fact(env: &FactEnv, x: u32) -> u32 {
if x == 0 {env.base_case} else {x * fact(env, x - 1)}
}
let env = FactEnv { base_case: 1 };
println!("{}", fact(&env, 5));
}
All of these work with Rust 1.17 and have probably worked since version 0.6. The fn's defined inside fns are no different to those defined at the top level, except they are only accessible within the fn they are defined inside.
As of Rust 1.62 (July 2022), there's still no direct way to recurse in a closure. As the other answers have pointed out, you need at least a bit of indirection, like passing the closure to itself as an argument, or moving it into a cell after creating it. These things can work, but in my opinion they're kind of gross, and they're definitely hard for Rust beginners to follow. If you want to use recursion but you have to have a closure, for example because you need something that implements FnOnce() to use with thread::spawn, then I think the cleanest approach is to use a regular fn function for the recursive part and to wrap it in a non-recursive closure that captures the environment. Here's an example:
let x = 5;
let fact = || {
fn helper(arg: u64) -> u64 {
match arg {
0 => 1,
_ => arg * helper(arg - 1),
}
}
helper(x)
};
assert_eq!(120, fact());
Here's a really ugly and verbose solution I came up with:
use std::{
cell::RefCell,
rc::{Rc, Weak},
};
fn main() {
let weak_holder: Rc<RefCell<Weak<dyn Fn(u32) -> u32>>> =
Rc::new(RefCell::new(Weak::<fn(u32) -> u32>::new()));
let weak_holder2 = weak_holder.clone();
let fact: Rc<dyn Fn(u32) -> u32> = Rc::new(move |x| {
let fact = weak_holder2.borrow().upgrade().unwrap();
if x == 0 {
1
} else {
x * fact(x - 1)
}
});
weak_holder.replace(Rc::downgrade(&fact));
println!("{}", fact(5)); // prints "120"
println!("{}", fact(6)); // prints "720"
}
The advantages of this are that you call the function with the expected signature (no extra arguments needed), it's a closure that can capture variables (by move), it doesn't require defining any new structs, and the closure can be returned from the function or otherwise stored in a place that outlives the scope where it was created (as an Rc<Fn...>) and it still works.
Closure is just a struct with additional contexts. Therefore, you can do this to achieve recursion (suppose you want to do factorial with recursive mutable sum):
#[derive(Default)]
struct Fact {
ans: i32,
}
impl Fact {
fn call(&mut self, n: i32) -> i32 {
if n == 0 {
self.ans = 1;
return 1;
}
self.call(n - 1);
self.ans *= n;
self.ans
}
}
To use this struct, just:
let mut fact = Fact::default();
let ans = fact.call(5);

Resources