zoukankan      html  css  js  c++  java
  • FnOnce , FnMut <RUST>

    
    

    FnOnce 

    1 #[lang = "fn_once"]
    2 #[must_use = "closures are lazy and do nothing unless called"]
    3 pub trait FnOnce<Args> {
    4     type Output;
    5     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
    6 }

    The version of the call operator that takes a by-value receiver.

    Instance of FnOnce can be called, but might not be callable multiple times. Because of this, if the only thing known about a type is that it implements FnOnce, it can only be called once.

    FnOnce is implemented automatically by closure that might consumer captured variable, as well as all types that implement FnMut, e.g(safe)function pointer (since FnOnce is a supertrait of FnMut).

    Since both Fn and FnMut are subtraits of FnOnce, any instance of Fn or FnMut can be used where a FnOnce is expected.

    Use FnOnce as a bound when you want to accept a parameter of function-like type and only need to call it once. If you need to call the parameter repeatedly, use FnMut as a bound; if you also need it to not mutate state, use Fn.

    Aslo of note is the sapcial syntax for Fn traits(e.g Fn(usize, bool) -> usize). Those interested in the technical details of this can refer to the relevant section in the Rustonmicon.

     1 fn consume_with_relish<F>(func: F) 
     2     where F: FnOnce() -> String
     3 {
     4     // 'func' consumers it captured variables, so it cannot be run more than once.
     5     println!("Consumed: {}", func());
     6     
     7     println!("Delicious!");
     8 
     9     //Attempting to invoke 'func()' again will therow a 'use of moved 
    10     // value 'error for 'func'
    11 }
    12 
    13 let x = String::from("x");
    14 let consume_and_return_x = move || x;
    15 consume_with_relish(consume_and_return_x);

     FnMut 

    1 Trait std::ops::FnMut
    2 
    3 #[lang = "fn_mut"]
    4 #[must_use = "clousure are lazy and do nothing unless called"]
    5 pub trait FnMut<Args>: FnOnce<Args> {
    6     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
    7 }

    The version of the call operator that takes a mutale receiver.

    Instance of FnMut can be called repeatedly and many mutate state.

    FnMut is implemented automatically by closures which take mutable reeferences to captured variables, as well as all types that implement Fn, e.g, (safe) functuin pointer(since FnMut is a supertrait of Fn). Additionally, for any type F that implements FnMut, &mut F implements FnMut, too.

     1 pub fn map<F, T, U>(values: Vec<T>, mut f: F) -> Vec<U> 
     2     where F: FnMut(T) -> U, {
     3     let mut v = Vec::with_capacity(values.len());
     4     for val in vlaues { 
     5         v.push(f(val));
     6     }
     7     v
     8 }
     9 
    10 
    11 fn square(x: i32) -> i32 {
    12     x * x
    13 }
    14 
    15 #[test]
    16 fn func_single() {
    17     let input = vec![2];
    18     let expected = vec![4];
    19     assert_eq!(map(input, square), expected);
    20 }
    21 
    22 #[test]
    23 #[ignore]
    24 fn func_multi() {
    25     let input = vec![2, 3, 4, 5];
    26     let expected = vec![4,9,16,25];
    27     assert_eq!(map(input, square),expected);
    28 }
    29 
    30 #[test]
    31 #[ignore]
    32 fn closure() {
    33     let input = vec![2, 3, 4, 5];
    34     let expected = vec![4,9, 16, 25];
    35     assert_eq!(map(input, |x| x*x), expected);
    36 }
    37 
    38 #[test]
    39 #[ignore]
    40 fn closure_floats() {
    41     let input = vec![2.0, 3.0, 4.0, 5.0];
    42     let expected  = vec![4.0, 9.0, 16.0, 25.0];
    43     assert_eq!(map(input, |x| x*x), expected);
    44 }
    45 
    46 #[test]
    47 #[ignore]
    48 fn strings() {
    49     let input = vec!["1".to_stirng(), "2".into(), "3".into()];
    50     let expected = vec!["11".to_string(), "22".into(), "33".into()];
    51     assert_eq!(map(input, |s| s.repeat(2)), expected);
    52 }
    53 
    54 
    55 #[test]
    56 #[ignore]
    57 fn change_in_type() {
    58     let input: Vec<&str> = vec!["1", "2", "3"];
    59     let expected: Vec<String> = vec!["1".into(), "2".into(), "3".into()];
    60     assert_eq!(map(input, |s| s.to_string()), expected);
    61 }
    62 
    63 #[test]
    64 #[ignore]
    65 fn mutaing_closure() {
    66     let mut counter = 0;
    67     let input = vec![-2, 3, 4, -5];
    68     let expected = vec![2, 3, 4,5];
    69     let result = map(input, |x:i64| {
    70         counter += 1;
    71         x.abs()
    72     });
    73     assert_eq!(result, expected);
    74     assert_eq!(counter, 4);
    75 }
    76 
    77 #[test]
    78 #[ignore]
    79 fn minimal_bounds_on_input_and_output() {
    80     // mut be able to accept arbitrary input and output types
    81     struct Foo;
    82     struct Bar;
    83     map(vec![Foo], |_| Bar);
    84 }
  • 相关阅读:
    如何将jar包加入到Maven本地仓库
    dubbo 常见错误
    关于spring”通配符的匹配很全面, 但无法找到元素 'context:component-scan' 的声明“的错误
    Maven类包冲突终极三大解决技巧 mvn dependency:tree
    springMVC传对象参数
    scp 对拷文件夹 和 文件夹下的所有文件 对拷文件并重命名
    CATALINA_BASE与CATALINA_HOME的区别
    有return的情况下try catch finally的执行顺序(最有说服力的总结)
    Slf4j MDC 使用和 基于 Logback 的实现分析
    Docker 系列01: Centos7.3 上安装docker
  • 原文地址:https://www.cnblogs.com/Davirain/p/13373683.html
Copyright © 2011-2022 走看看