Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Functional programming 如何在不创建闭包的情况下调用多参数函数?_Functional Programming_Rust_Iterator_Currying - Fatal编程技术网

Functional programming 如何在不创建闭包的情况下调用多参数函数?

Functional programming 如何在不创建闭包的情况下调用多参数函数?,functional-programming,rust,iterator,currying,Functional Programming,Rust,Iterator,Currying,我是在铁锈中做溶液时遇到这个问题的 要解决的问题: 取两个字母完全相同的字符串数乘以三个字母完全相同的字符串数 输入 abcdega hihklmh abqasbb AABCD 第一个字符串abcdega重复了a两次 第二个字符串hihklmh重复了h三次 第三个字符串abqasbb重复了a两次,而b重复了三次,因此它对这两个字符串都有效 第四个字符串aaaabcd包含一个重复4次的字母(不是2次,或3次),因此它不计数 因此,结果应该是: 2包含双字母(第一个和第三个)的字符串乘以2包含

我是在铁锈中做溶液时遇到这个问题的

要解决的问题:

取两个字母完全相同的字符串数乘以三个字母完全相同的字符串数

输入

abcdega hihklmh abqasbb AABCD
  • 第一个字符串
    abcdega
    重复了
    a
    两次
  • 第二个字符串
    hihklmh
    重复了
    h
    三次
  • 第三个字符串
    abqasbb
    重复了
    a
    两次,而
    b
    重复了三次,因此它对这两个字符串都有效
  • 第四个字符串
    aaaabcd
    包含一个重复
    4次的字母(不是
    2次
    ,或
    3次
    ),因此它不计数
因此,结果应该是:

2
包含双字母(第一个和第三个)的字符串乘以
2
包含三个字母(第二个和第三个)的字符串
=4

问题

const PUZZLE_INPUT: &str = 
"
abcdega
hihklmh
abqasbb
aaaabcd
";

fn letter_counts(id: &str) -> [u8;26] {
    id.chars().map(|c| c as u8).fold([0;26], |mut counts, c| { 
        counts[usize::from(c - b'a')] += 1;
        counts 
    })
}

fn has_repeated_letter(n: u8, letter_counts: &[u8;26]) -> bool {
    letter_counts.iter().any(|&count| count == n)
}

fn main() {
    let ids_iter = PUZZLE_INPUT.lines().map(letter_counts);
    let num_ids_with_double = ids_iter.clone().filter(|id| has_repeated_letter(2, id)).count();
    let num_ids_with_triple = ids_iter.filter(|id| has_repeated_letter(3, id)).count();
    println!("{}", num_ids_with_double * num_ids_with_triple);
}

考虑第21行
21
。函数
letter\u counts
只接受一个参数,因此我可以对与预期参数类型匹配的元素使用语法:
.map(letter\u counts)
。这对我真的很好!我喜欢不必创建闭包:
.map(|id | letter_counts(id))
。我发现两者都可读,但没有闭包的前一个版本对我来说要干净得多

现在考虑行<代码> 22 <代码>和<代码> 23 < /代码>。这里,我必须使用语法:

.filter(|id | has _repeated _letter(3,id))
,因为
has _repeated _letter
函数包含两个参数。我真的想做
.filter(重复字母(3))

当然,我可以让函数取一个元组,映射到一个元组,只使用一个参数。。。但这似乎是一个糟糕的解决方案。我宁愿创建一个闭包

只忽略参数是Rust允许您做的事情。如果编译器为一个接受
n
参数的函数提供了所有其他
n-1
参数,那么编译器为什么更难让您省略最后一个参数呢

我觉得这样做会使语法更清晰,并且更适合Rust喜欢的惯用函数式风格


我当然不是编译器专家,但实现这种行为似乎很简单。如果我的想法是错误的,我想知道更多的原因

否,不能将具有多个参数的函数作为隐式闭包传递

在某些情况下,您可以选择使用来减少函数的算术性。例如,这里我们将
add
函数从两个参数减少为一个:

fn add(a: i32, b: i32) -> i32 {
    a + b
}

fn curry<A1, A2, R>(f: impl FnOnce(A1, A2) -> R, a1: A1) -> impl FnOnce(A2) -> R {
    move |a2| f(a1, a2)
}

fn main() {
    let a = Some(1);
    a.map(curry(add, 2));
}
  • curry
    功能非常有限:它选择使用
    FnOnce
    ,但是
    Fn
    FnMut
    也有用例。它只适用于具有两个参数的函数


  • 但是,在其他项目中,这种高阶函数技巧的添加量要大得多。

    您要做的是“curry”或“partial function application”,这在Rust中不直接支持。编写lambda实际上是实现这一点的惯用方法。想象一个函数
    fn foo(a:i32,b:i32){…}
    ,然后将其称为
    fn main(){foo(4);}
    ,根据您的建议,此代码将是合法的,但不起任何作用。IMHO说,在真正需要的时候编写一个lambda,比如
    |x | foo(4,x)
    ,要合理得多。此外,您还可以轻松编写
    |x | foo(x,4)
    或任何其他具有任意数量参数的变体,而不影响语言的其余部分。当然,您可以编写一个宏,该宏接受这些参数并扩展为lambda,但是,
    应用的优点是什么!(HaspRealthEdType,3)过<代码> x x Hasz重复字母(3,x)< /代码>?你的问题基本上可以归结为“我可以做这个[一个参数示例],我如何做这个[两个参数示例]”(代码的出现基本上与问题完全无关)这将使其他人更难阅读这个问题,当他们有一个潜在的复制品时,他们会知道它是否与他们相关。
    
    a.map(curry(add, 2));
    a.map(|v| add(v, 2));