我一直在Project Euler上练习F#技能。在做问题19(在酷problem 18之后发生激烈的反对声)时,我发现自己需要在数字列表上执行模7运算。我试过这个:
List.map ((%) 7)
最终得到了错误的数字列表。那是因为List.map
绑定了第二个参数,所以不是计算n%7而是计算7%n。有没有办法让List.map
绑定第一个参数,或者是翻转这两个参数的标准方法?
我知道我可以使用fun n->n%7
代替(%) 7
,但我希望有更短的解决方案。
答案 0 :(得分:3)
其他人已经指出,这可以通过从Haskell定义flip
函数来完成。但是,我建议使用lambda函数或使用列表推导显式编写代码(更短并避免使用显式lambdas):
inputs |> List.map (fun n-> n % 7)
[ for n in inputs -> n % 7 ]
使用翻转的参数定义一个行为类似moduloBy
的辅助函数%
可能是个好主意:
let moduloBy n input = input % n
inputs |> List.map (moduloBy 7)
原因是可读性。虽然欧拉问题是玩具的例子,但编写易于理解的代码非常重要。这在F#中更为重要,因为编写非常难以理解的代码非常容易。我认为您同意阅读上述代码段比阅读更容易(并且使用flip
的解决方案也不会明显缩短):
inputs |> List.map ((flip (%)) 7)
答案 1 :(得分:2)
您可以为此目的定义flip
:
namespace Microsoft.FSharp.Core
module Operators =
let flip f x y = f y x
这是在函数式编程语言中这样做的一种相当常见的方式。例如,Haskell还有一个flip
函数in its Prelude。
答案 2 :(得分:2)
flip
功能:
let inline flip f a b = f b a
通常用于此任务。现在,您可以将flip (%) 7
直接传递给List.map
。
这称为无点样式,在Haskell中很流行但在F#社区中并不常见。问题是,在许多情况下,它可能使程序难以阅读和难以维护。