在OCaml或F#中通常以以下形式进行连续的let绑定:
let a1 = ...
let a2 = ...
let a3 = ...
let f1 = ...
let f2 = ...
let f3 = ...
f3 a1 a2 a3
在许多情况下,其中一些让绑定(例如上面示例中的 f1 和 f2 )仅用作表达式或函数的构建块,紧跟在它们之后之后再没有引用。在其他情况下,某些值确实在“链”的末尾使用(例如,上面示例中的 a1 , a2 和 a3 )。是否存在任何语法习惯用语来明确范围内的这些差异?
答案 0 :(得分:11)
开启可以使用它来明确temp
仅用于a1
的定义:
let a1 =
let temp = 42 in
temp + 2 in
let a2 = ...
temp
的范围确实仅限于a1
的定义。
另一个模板正在重复使用相同的名称来隐藏其先前的用途,因此也明确表示以前的使用是暂时的:
let result = input_string inchan in
let result = parse result in
let result = eval result in
result
重用相同的名称是值得商榷的。
当然,总会有评论和空行:
let a1 = ...
let a2 = ...
let a3 = ...
(*We now define f3:*)
let f1 = ...
let f2 = ...
let f3 = ...
f3 a1 a2 a3
编辑:正如fmr所指出的,我也喜欢管道操作员。它在OCaml中没有默认定义,使用
let (|>) x f = f x;;
然后你可以写点像
input_string inchan |> parse |> eval |> print
答案 1 :(得分:7)
除了jrouquie的答案,你可以通过明智地使用函数组合和其他组合器来避免给中间值命名。我特别喜欢Batteries提供的以下三个:
# let ( |> ) x f = f x;;
val ( |> ) : 'a -> ('a -> 'b) -> 'b = <fun>
# let ( |- ) f g x = g (f x);;
val ( |- ) : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c = <fun>
# let flip f x y = f y x;;
val flip : ('a -> 'b -> 'c) -> 'b -> 'a -> 'c = <fun>
使用|>
的一个小例子是
# [1;2;3]
|> List.map string_of_int
|> String.concat "; "
|> Printf.sprintf "[%s]";;
- : string = "[1; 2; 3]"
在更实际的示例中,您最终需要|-
和flip
。这称为point-free或tacit编程。