我正在将一些F#代码转换为OCaml,我看到了这个管道运算符的很多用途<|,例如:
let printPeg expr =
printfn "%s" <| pegToString expr
Run Code Online (Sandbox Code Playgroud)
该<|运营商显然是定义为只是:
# let ( <| ) a b = a b ;;
val ( <| ) : ('a -> 'b) -> 'a -> 'b = <fun>
Run Code Online (Sandbox Code Playgroud)
我想知道为什么他们懒得在F#中定义和使用这个操作符,是不是就这样他们可以避免像这样放入一些parens?:
let printPeg expr =
Printf.printf "%s" ( pegToString expr )
Run Code Online (Sandbox Code Playgroud)
据我所知,这将是上面的F#代码转换为OCaml,对吗?
另外,我如何在Ocaml中实现F#<<和>>运算符?
(该|>操作似乎仅仅是:let ( |> ) a b = b a ;;)
byt*_*ter 15
为什么他们懒得在F#中定义和使用这个操作符,是不是因为他们可以避免放入parens?
这是因为编程的功能性假设通过一系列函数来线程化一个值.相比:
let f1 str server =
str
|> parseUserName
|> getUserByName server
|> validateLogin <| DateTime.Now
let f2 str server =
validateLogin(getUserByName(server, (parseUserName str)), DateTime.Now)
Run Code Online (Sandbox Code Playgroud)
在第一个片段中,我们清楚地看到了价值所发生的一切.阅读第二篇文章,我们必须仔细检查所有正在发生的事情.
所以,是的,在正常的生活中,它主要是关于parens.而且,管道运营商与部分功能应用和无点编码风格密切相关.例如,请参阅编程"无意义".
管道|>和函数组合>> <<运算符在传递给更高级别的函数时可以产生另一个有趣的效果,就像这里一样.
ild*_*arn 12
直接来自F#源:
let inline (|>) x f = f x
let inline (||>) (x1,x2) f = f x1 x2
let inline (|||>) (x1,x2,x3) f = f x1 x2 x3
let inline (<|) f x = f x
let inline (<||) f (x1,x2) = f x1 x2
let inline (<|||) f (x1,x2,x3) = f x1 x2 x3
let inline (>>) f g x = g(f x)
let inline (<<) f g x = f(g x)
Run Code Online (Sandbox Code Playgroud)
luk*_*afi 10
OCaml Batteries支持这些运算符,但出于优先级,关联性和其他语法怪癖(如Camlp4)的原因,它使用不同的符号.最近使用的特定符号刚刚解决,有一些变化.请参阅:电池API:
val (|>) : 'a -> ('a -> 'b) -> 'b
Run Code Online (Sandbox Code Playgroud)
功能应用.x |> f相当于f x.
val ( **> ) : ('a -> 'b) -> 'a -> 'b
Run Code Online (Sandbox Code Playgroud)
功能应用.f**> x相当于f x.注意此运算符的名称不是一成不变的.它必将很快改变.
val (|-) : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c
Run Code Online (Sandbox Code Playgroud)
功能构成.f | - g很有趣x - > g(fx).这相当于应用<**两次.
val (-|) : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b
Run Code Online (Sandbox Code Playgroud)
功能构成.f - | g很有趣x - > f(gx).在数学上,这是运算符o.
但电池后备箱提供:
val ( @@ ) : ('a -> 'b) -> 'a -> 'b
Run Code Online (Sandbox Code Playgroud)
功能应用.[f @@ x]相当于[fx].
val ( % ) : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b
Run Code Online (Sandbox Code Playgroud)
函数组成:数学[o]运算符.
val ( |> ) : 'a -> ('a -> 'b) -> 'b
Run Code Online (Sandbox Code Playgroud)
"管道":功能应用程序.[x |> f]相当于[fx].
val ( %> ) : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c
Run Code Online (Sandbox Code Playgroud)
管道功能组成.[f%> g]是[有趣的x - > g(fx)].
我想知道为什么他们懒得在F#中定义和使用这个操作符,是不是就这样他们可以避免像这样放入这样的parens?
好问题.您所指的特定运算符(<|)是非常无用的IME.它允许您在极少数情况下避免使用括号,但更一般地说,它通过拖动更多运算符使语法复杂化,并使经验较少的F#程序员(现在有很多)更难理解您的代码.所以我已经停止使用它了.
该|>运营商更加有用的,但仅仅是因为它有助于F#正确地推断类型的情况下OCaml中不会有问题.例如,这里有一些OCaml:
List.map (fun o -> o#foo) os
Run Code Online (Sandbox Code Playgroud)
直接等价在F#中失败,因为在o读取其foo属性之前无法推断出类型,因此惯用解决方案是使用|>这样重写代码,因此F#可以推断出使用o之前的类型foo:
os |> List.map (fun o -> o.foo)
Run Code Online (Sandbox Code Playgroud)
我很少使用其他运算符(<<和>>),因为它们也使语法复杂化.我也不喜欢解析大量运算符的解析器组合库.
Bytebuster的例子很有意思:
let f1 str server =
str
|> parseUserName
|> getUserByName server
|> validateLogin <| DateTime.Now
Run Code Online (Sandbox Code Playgroud)
我会这样写:
let f2 str server =
let userName = parseUserName str
let user = getUserByName server userName
validateLogin user DateTime.Now
Run Code Online (Sandbox Code Playgroud)
我的代码中没有括号.我的临时工具有名称,所以它们出现在调试器中,我可以检查它们,当我将鼠标悬停在它们上面时,Intellisense可以给我类型回归.这些特性对于非专业F#程序员将要维护的生产代码很有价值.
| 归档时间: |
|
| 查看次数: |
2204 次 |
| 最近记录: |