2

Trying to learn Rust and seems that I am having a hard time finding how to return a function with 0.13 (nightly). My basic example is trying to deal with immutable arguments, so I would expect the below to work. When I read online, it seems that in 0.13 the behavior will change (so everything I read online doesn't seem to work).

$ rustc --version
rustc 0.13.0-nightly (62fb41c32 2014-12-23 02:41:48 +0000)

Just got up to http://doc.rust-lang.org/0.12.0/guide.html#accepting-closures-as-arguments and the next logical step is return a closure. When I do so, the compiler says that I can not

#[test]
fn test_fn_return_closure() {
  fn sum(x: int) -> |int| -> int {
    |y| { x + y }
  }

  let add3 = sum(3i);
  let result: int = add3(5i);

  assert!(result == 8i);
}

/rust-lang-intro/closures/tests/lib.rs:98:21: 98:33 error: explicit lifetime bound required
/rust-lang-intro/closures/tests/lib.rs:98   fn sum(x: int) -> |int| -> int {
                                                                                                   ^~~~~~~~~~~~
error: aborting due to previous error
Could not compile `closures`.

I tried returning a reference to see if that would help

let sum = |x: int| {
  &|y: int| { x + y }
};
let add3 = *(sum(3i));

but when you try to use it, you get a even more verbose error

/rust-lang-intro/closures/tests/lib.rs:102:6: 102:24 error: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
/rust-lang-intro/closures/tests/lib.rs:102     &|y: int| { x + y }
                                                ^~~~~~~~~~~~~~~~~~
/rust-lang-intro/closures/tests/lib.rs:105:14: 105:25 note: first, the lifetime cannot outlive the expression at 105:13...
/rust-lang-intro/closures/tests/lib.rs:105   let add3 = *(sum(3i));
                                                        ^~~~~~~~~~~
/rust-lang-intro/closures/tests/lib.rs:105:14: 105:25 note: ...so that pointer is not dereferenced outside its lifetime
/rust-lang-intro/closures/tests/lib.rs:105   let add3 = *(sum(3i));
                                                        ^~~~~~~~~~~
/rust-lang-intro/closures/tests/lib.rs:102:6: 102:24 note: but, the lifetime must be valid for the expression at 102:5...
/rust-lang-intro/closures/tests/lib.rs:102     &|y: int| { x + y }
                                                ^~~~~~~~~~~~~~~~~~
/rust-lang-intro/closures/tests/lib.rs:102:6: 102:24 note: ...so type `|int| -> int` of expression is valid during the expression
/rust-lang-intro/closures/tests/lib.rs:102     &|y: int| { x + y }
                                                                                     ^~~~~~~~~~~~~~~~~~
error: aborting due to previous error
Could not compile `closures`.

So, I assume that I need to save the pointer, and only dereference when I need it, but seems that the error message is basically the same.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
ekaqu
  • 2,038
  • 3
  • 24
  • 38
  • the selected answer no longer works. If you try them in rust playpen, they no longer compile. – ekaqu Dec 29 '14 at 07:42
  • the example has been updated. In the future, you should point out duplicate questions and why they don't apply to your new situation. – Shepmaster Dec 29 '14 at 14:13
  • Thanks! I updated the nullary example so it will compile now. Any idea if/when Fn family will allow a shorter syntax, such as foo(1) rather than foo.call((1,)) – ekaqu Dec 29 '14 at 16:26
  • Nope, but I see that "Disallow direct calls to foo.call()" is [part of 1.0](https://github.com/rust-lang/rust/issues/18875). – Shepmaster Dec 29 '14 at 17:07
  • Oh, here are [two](https://github.com/rust-lang/rust/issues/16929) [more](https://github.com/rust-lang/rust/issues/19187) references. – Shepmaster Dec 29 '14 at 17:09

1 Answers1

2

In current 1.1.0 era Rust this is well documented.

#[cfg(test)]
mod tests {
    // the `type` is not needed but it makes it easier if you will
    // be using it in other function declarations.
    type Adder = Fn(i32) -> i32;

    fn sum(x: i32) -> Box<Adder> {
        Box::new(move |n: i32| x + n)
    }

    #[test]
    fn it_works() {
        let foo = sum(2);
        assert_eq!(5, foo(3));
    }
}

See the Rust docs for more details.

Sean Perry
  • 3,776
  • 1
  • 19
  • 31