F#定义的首选样式是什么?
我正在学习的book经常使用以下风格:
assertTrue($count === 1)
另一方面,当我在网上查找信息时,最有可能遇到以下情况:
let foo = fun x y ->
let aux1 = fun z -> z * 2
in aux1 x +
let aux2 = fun q -> q * 3
in aux2 y;;
在Guide我找不到关于它的参考。这是一个超越“纯粹的风格”的问题吗?这两种方法背后有效率影响吗?
您的经验表明了什么?
答案 0 :(得分:4)
作为一般规则,F#函数定义倾向于执行以下两种操作之一:
定义尽可能少的类型(let foo x y = ...
)。大多数功能都是这种情况。或...
明确定义每个参数的类型和返回类型(let foo (x : int) (y : int) : int = ...
。
样式#2很少见,而且我经常看到它是明确属于模块API的函数,并且还有///
个注释来提供文档。但是,对于内部函数,通常使用无类型变体,因为F#的类型推断效果很好。
此外,正如s952163在评论中指出的那样,in
关键字几乎不再使用,因为#light
样式使其不必要。我希望看到您的示例代码在现代F#样式中编写如下:
let foo x y =
let aux1 z = z * 2
let aux2 q = q * 3
(aux1 x) + (aux2 y)
除非您要在F#Interactive控制台中输入,否则不需要;;
。如果您正在使用VS Code + Ionide,并突出显示代码段并按 Alt + Enter 将其发送到F#Interactive,那么您不需要任何;;
隔离因为Ionide会自动添加它们。
答案 1 :(得分:1)
我发现有证据表明第一种风格,即使今天是非传统风格,也与cur and和匿名功能有着内在的联系。
Currying是F#的强大特性,我记得,每个函数都只能使用一个参数。例如:
let add x y = x + y
val add: int -> int -> int
签名被解释为 add 是一个函数,它将两个整数作为输入并返回一个整数。 当编译时间到来时,该函数被解释为:
let add2 = fun x -> fun y -> x + y
val add2: int -> int -> int
其中val add2: int -> int -> int
在语义上等同于val add: (int -> (int -> int))
通过向add2
提供参数,例如6
,它返回fun y -> 6 + y
,这是另一个等待其参数的函数,而x
被{6
替换1}}。
Currying意味着每个参数实际上都返回一个单独的函数:这就是为什么当我们调用只有少数参数的函数时会返回另一个函数。
如果我得到了正确的话,第二个例子let add x y = x + y
的更常见的F#语法可以被认为是上面显示的显式currying风格的语法糖。