实施管道运营商的成本

时间:2013-02-03 23:29:47

标签: f#

我正在使用一种名为'elm'的语言,它试图将Haskel-esque语法和FRP引入Javascript。这里有一些关于从F#实现管道运算符的讨论,但语言设计者担心增加的成本(我假设增加的编译时间或编译器实现复杂性)超过更标准(至少在其他FP语言中)反向管道运算符(榆树已经实施)。谁能说到这个? [请随意直接发布到该主题,否则我将回复最佳答案,如果没有其他人这样做的话。)

https://groups.google.com/forum/?fromgroups=#!topic/elm-discuss/Kt0MbDyRpO4

谢谢!

3 个答案:

答案 0 :(得分:7)

在你参考的讨论中,我看到埃文提出了两个挑战:

  1. 向我展示一些使用它的F#项目
  2. 找一些可靠的F#程序员,谈论为什么这是一个好主意,以及它带来的成本(博客文章或其他东西)。
  3. 我的答案如下:

    1. 前向管道习惯在F#编程中很常见,既有风格(我们喜欢它)和实用(它有助于类型推断)的原因。几乎任何你会发现的F#项目都会经常使用它。当然我的所有开源项目都使用它(Unquote,FsEye,NL found here)。毫无疑问,你会发现包括F#编译器源本身在内的所有Github located F# projects都是一样的。

    2. Brian,微软F#编译团队的开发人员,在2008年发表了关于Pipelining in F#的博客,这是一个非常有趣且相关的博客,它将F#管道与POSIX管道相关联。根据我自己的估计,实施管道操作员的成本非常低。在F#编译器中,这在任何意义上都是正确的(它是一行的内联函数定义)。

答案 1 :(得分:3)

管道运算符实际上非常简单 - 这是标准定义

let inline (|>) a b = b a

此外,线程中讨论的.运算符是F#(<|)中的反向管道运算符,它允许您删除一些括号。

我认为添加管道运营商不会对复杂性产生重大影响

答案 2 :(得分:2)

除了这里已经给出的优秀答案之外,我还想补充几点。

首先,管道运算符在F#中很常见的原因之一是它有助于避免当前类型推断方式的缺点。具体来说,如果使用lambda函数应用聚合操作,该函数使用OOP进行集合类型推断通常会失败。例如:

Seq.map (fun z -> z.Real) zs

这会失败,因为F#在遇到属性z时还不知道Real的类型,所以它拒绝编译此代码。惯用的解决方法是使用管道运算符:

xs |> Seq.map (fun z -> z.Real)

这是非常丑陋的(IMO),但它确实有效。

其次,F#管道运算符很适合某一点,但您目前无法获得中间结果的推断类型。例如:

x
|> h
|> g
|> f

如果f出现类型错误,那么程序员会想知道输入f的值的类型,以防问题实际上是h或{{ 1}}但目前在Visual Studio中不可能。具有讽刺意味的是,对于Emacs,使用图阿雷格模式在OCaml中很容易,因为您可以获得任何子表达式的推断类型,而不仅仅是标识符。