Given the following rust program:
fn call_twice<A>(val: A, f: fn(A) -> A) -> A {
f(f(val))
}
fn main() {
fn double(x: int) -> int {x + x};
println!("Res is {}", call_twice(10i, double));
// println!("Res is {}", call_twice(10i, (x: int) -> int {x + x}));
// ^ this line will fail
}
Why can I pass double as the function, but not inlined? What is a good way to achieve the same behaviour without defining the function somewhere?
2016-04-01 Update:
As of Rust 1.0, the code should look like this:
fn call_twice<A, F>(val: A, mut f: F) -> A
where F: FnMut(A) -> A {
let tmp = f(val);
f(tmp)
}
fn main() {
fn double(x: i32) -> i32 {x + x};
println!("Res is {}", call_twice(10, double));
println!("Res is {}", call_twice(10, |x| x + x));
}
The change to the closure parameter is because closure are now unboxed.
Original:
Insofar as I know, you can't define functions inline like that.
What you want is a closure. The following works:
fn call_twice<A>(val: A, f: |A| -> A) -> A {
let tmp = f(val);
f(tmp)
}
fn main() {
fn double(x: int) -> int {x + x};
println!("Res is {}", call_twice(10i, double));
println!("Res is {}", call_twice(10i, |x| x + x));
}
There are a few things to note:
Functions coerce to closures, but the opposite isn't true.
You need to store the result of f(val) in a temporary due to borrowing rules. Short version: you need unique access to a closure to call it, and the borrow checker isn't quite clever enough to realise the two calls are independent in their original positions.
Closures are in the process of being replaced by unboxed closures, so this will change in the future, but we're not quite there yet.
Related
I'm trying to write code like the following, but where I apply f1 and f2 some variable number of times:
#![feature(impl_trait_in_bindings)]
fn f1(c: char) -> impl IntoIterator<Item = char> {
vec!['A', c]
}
fn f2(c: char) -> impl IntoIterator<Item = char> {
vec!['C', 'D', c]
}
fn main() {
let x = vec!['X', 'X', 'X'];
let v: impl Iterator<Item = char> = x.into_iter();
let v = v.flat_map(f1);
let v = v.flat_map(f2);
println!("Force evaluation of five elements: {:?}", v.take(5).collect::<Vec<_>>());
}
I'd like to replace the let v = ... lines with a loop that iteratively reassigns v, like
let mut v: impl Iterator<Item = char> = x.into_iter();
for i in 0..f1Times {
v = v.flat_map(f1);
}
for i in 0..f2Times {
v = v.flat_map(f2);
}
... e.g. for my use case I may have several functions and I won't know which ones (or how many times) to apply ahead of time. I'd like the result to be an iterator that I can take only a limited number of items from, and I'd like to avoid invoking any functions that aren't needed to generate those items.
I can't get the types to work. For instance with the let mut block I proposed above I get:
mismatched types
expected opaque type `impl Iterator`
found struct `FlatMap<impl Iterator, impl IntoIterator, fn(char) -> impl IntoIterator {f1}>`
Is there a good way to build up this sort of iterator programatically?
I've found this pattern works, but still don't know if it's idiomatic or recommended...
#![feature(impl_trait_in_bindings)]
fn f1(c: char) -> impl Iterator<Item = char> {
Box::new(vec!['A', c].into_iter())
}
fn f2(c: char) -> impl Iterator<Item = char> {
Box::new(vec!['C', 'D', c].into_iter())
}
fn main() {
let x = vec!['X', 'X', 'X'];
let mut v: Box<dyn Iterator<Item = char>> = Box::new(x.into_iter());
let f1_ntimes = 2;
for _i in 0..f1NTimes {
v = Box::new(v.into_iter().flat_map(f1));
}
let f2_ntimes = 2;
for _i in 0..f2_ntimes {
v = Box::new(v.into_iter().flat_map(f2));
}
println!("Force evaluation of five elements: {:?}", v.take(5).collect::<Vec<_>>());
}
I attempt to implement a currying function similar to Functional Programming Jargon in Rust:
fn add_origin(x: i32) -> impl Fn(i32) -> i32 {
return move |y| {
x + y
};
}
fn main() {
let add5 = add_origin(5);
println!("Call closure: {}", add5(6));
}
This works, but if I add one level deeper:
fn add(x: i32) -> impl Fn(i32) -> impl Fn(i32) -> i32 {
return move |y: i32| {
return move |z: i32| {
x + y + z
}
};
}
fn main() {
let add5 = add(5);
let add5_10 = add5(10);
println!("Call closure: {}", add5_10(6));
}
Compiler does not accept and tells me:
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
--> src/main.rs:7:35
|
7 | fn add(x: i32) -> impl Fn(i32) -> impl Fn(i32) -> i32 {
| ^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
Why is this not allowed? Is there a better alternative in Rust?
impl Trait syntax can only be used in argument position or return position of a function signature. Both of these are fine:
fn takes_fn(fn_arg: impl Fn(i32) -> i32) {}
fn returns_fn() -> impl Fn(i32) -> i32 {
|x| x
}
However neither of these work:
fn takes_fn(fn_arg: impl Fn(i32) -> impl Fn(i32) -> i32) {}
fn returns_fn() -> impl Fn(i32) -> impl Fn(i32) -> i32 {
|x| x
}
Because the second nested impl Trait is no longer in argument or return position but is now part of the argument or return type's signature, which is not somewhere where it is allowed. Basically, multiple nested impl Traits will never work regardless of where you place them and you'll always get the same compile error.
The good news is this doesn't stop you from accomplishing what you want to accomplish because impl Trait is just syntax sugar and its use is optional. In your particular example we can use a boxed trait object to return your curried function.
fn add(x: i32) -> impl Fn(i32) -> Box<dyn Fn(i32) -> i32> {
move |y: i32| {
Box::new(move |z: i32| {
x + y + z
})
}
}
fn main() {
let add5 = add(5);
let add5_10 = add5(10);
println!("Call closure: {}", add5_10(6)); // prints "Call closure: 21"
}
playground
See also:
What does `impl` mean when used as the argument type or return type of a function?
What makes `impl Trait` as an argument "universal" and as a return value "existential"?
This question already has answers here:
How do you pass a Rust function as a parameter?
(2 answers)
Closed 4 years ago.
fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 { // definition
f(arg) + f(arg)
}
do_twice(|x| x + 1, 5) // call
This function accepts both, closures and function pointers. It takes a function pointer as parameter type.
When should I prefer this over using a trait object, like &dyn Fn(i32) -> i32 or Box<dyn Fn(i32)-> i32> instead of fn
fn do_twice(f: &dyn Fn(i32) -> i32, arg: i32) -> i32 { // definition
f(arg) + f(arg)
}
do_twice(&|x| x + 1, 5) // call
or
fn do_twice(f: Box<dyn Fn(i32) -> i32>, arg: i32) -> i32 { // definition
f(arg) + f(arg)
}
When should I prefer this over using a trait object
Trait objects are not the only other option. As #DarthKotik pointed out, accepting a fn pointer will not permit closures that capture their environment, but you can just use a normal type parameter, bounded by Fn to accept both functions and closures, without needing to box anything:
fn do_twice<F>(f: F, arg: i32) -> i32
where
F: Fn(i32) -> i32
{
f(arg) + f(arg)
}
Or, equivalently, but avoiding an extra type variable:
fn do_twice(f: impl Fn(i32) -> i32, arg: i32) -> i32 {
f(arg) + f(arg)
}
fn type is a bare function pointer (https://doc.rust-lang.org/std/primitive.fn.html).
It won't work with the closure that captures environment and it cannot be implemented manually for your fancy type (like impl Fn for MySuperType)
So the only reason why your examples working is the fact that it's oversimplified!
if you make it just a bit more complicated, it will fail https://gist.github.com/rust-play/2167e73325daa1e2a179505209405917
In this elementary Rust program a function calculates the absolute value of an integer, and main() helps in completing a statement with the result:
fn main() {
let value = abs(-4);
println!("{}.", value);
}
fn abs(x: i32) -> i32 {
print!("The abs value of {} is ", x);
if x > 0 {
return x;
} else {
-x
}
}
Is there a way to print correctly the whole statement "The abs value of... is..." into the abs() function? I tried unsuccessfully with
println!("The abs value of {} is {} ", x, x);
This always prints the value of the x parameter (e.g. -4, -4) so it's not correct.
And with
println!("The abs value of {} is {} ", x, abs(x));
But here, for some reason, Rust is not happy with recursion, gives a warning at compilation and then doesn't run the program.
The absolute value method is already defined; you do not need to implement it yourself
fn main() {
let value = abs(-4);
println!("{}.", value);
}
fn abs(x: i32) -> i32 {
let val = x.abs();
println!("The abs value of {} is {}", x, val);
val
}
Try this to avoid recursion:
fn main() {
let value = abs(-4);
println!("{}.", value);
}
fn abs(x: i32) -> i32 {
let y = if x >= 0 { x } else { -x };
println!("The abs value of {} is {} ", x, y);
y
}
Output:
The abs value of -4 is 4
4.
There are built-in .abs() method for primitive types e.g.
i8,
i16,
i32,
i64,
i128,
f32,
and f64:
assert_eq!(10i32.abs(), 10);
assert_eq!((-10i32).abs(), 10);
Overflow behavior
The absolute value of i32::min_value() cannot be represented as an
i32, and attempting to calculate it will cause an overflow. This
means that code in debug mode will trigger a panic on this case and
optimized code will return i32::min_value() without a panic.
The following code, will panic in debug mode (and returns -128 in release mode):
fn main() {
let a = -128_i8;
println!("{}", a); // -128
let b = a.abs();
println!("{}", b); // -128
}
Since abs(-2_147_483_648_i32) is 2_147_483_648_u32, you may return u32 instead of i32:
fn abs(x: i32) -> u32 {
if x >= 0 {
x as u32
} else if x == std::i32::MIN {
2_147_483_648_u32
} else {
-x as u32
}
}
fn main() {
let value = abs(std::i32::MIN); // i32::min_value() // -2_147_483_648i32
println!("{}.", value); // 2147483648
}
Output:
2147483648
Here is an example:
use std::iter::Filter;
use std::slice::Iter;
fn test(xs: &[i32]) -> Filter<Iter<i32>, fn(&&i32) -> bool> {
fn nothing(_: &&i32) -> bool { false }
let ys = xs.iter().filter(nothing);
ys
}
fn main () {
}
Compilation fails with:
src/main.rs:8:5: 8:7 error: mismatched types:
expected `core::iter::Filter<core::slice::Iter<'_, i32>, fn(&&i32) -> bool>`,
found `core::iter::Filter<core::slice::Iter<'_, i32>, fn(&&i32) -> bool {test1::nothing}>`
(expected fn pointer,
found fn item) [E0308]
src/main.rs:8 ys
^~
This is because the inferred type of ys has the type of a specific function item in it. In this particular case the issue is easy to fix: one can either explicitly specify the type without the function item in the binding, or avoid the let altogether.
Both of these work:
fn test(xs: &[i32]) -> Filter<Iter<i32>, fn(&&i32) -> bool> {
fn nothing(_: &&i32) -> bool { false }
let ys: Filter<Iter<i32>, fn(&&i32) -> bool> = xs.iter().filter(nothing);
ys
}
fn test(xs: &[i32]) -> Filter<Iter<i32>, fn(&&i32) -> bool> {
fn nothing(_: &&i32) -> bool { false }
xs.iter().filter(nothing)
}
Therefore, as the Reference says, indeed Rust is capable of performing this coercion itself. But what if the code was more complex and I had to perform this cast manually? How would I do this?
In this case as won’t work, and transmute seems to be an overkill, although, I believe, it would do the job.
You can actually cast using as:
fn test(xs: &[i32]) -> Filter<Iter<i32>, fn(&&i32) -> bool> {
fn nothing(_: &&i32) -> bool { false }
let ys = xs.iter().filter(nothing as fn(&&i32) -> bool);
^~~~~~~~~~~~~~~~~~~~
ys
}
However you need to use as to change the function's type, not the Filter type, as as is not allowed to change arbitrary types.
Personally, I consider the necessity of the cast a short-coming and hope that type inference will improve to the point it becomes unnecessary. The fact that it works for a direct return is a red-herring, it should probably work with an intermediate value too.