【问题标题】:Pipeline operator with member functions具有成员函数的管道运算符
【发布时间】:2016-12-24 22:30:20
【问题描述】:

我可以通过管道运算符使用模块的函数和静态成员函数。我可以将它与非静态成员函数一起使用吗?

我的班级:

type MyClass =
    class
        new() = {}

        member this.isZero(number: int): bool =
            number = 0

        static member returnInt(): int =
            33
    end

使用静态成员:

MyClass.returnInt() |> Console.WriteLine // prints 33

使用非静态成员:

let foo = new MyClass()
foo.isZero(2) |> Console.WriteLine // prints false

我想使用对象中的非静态函数。无效语法:

let foo = new MyClass()
foo |> member MyClass.isZero(2) |> Console.WriteLine

我正在尝试使用 F# 的清晰语法。

【问题讨论】:

  • 你试图实现“使用非静态成员”下的代码不起作用的什么? member 从未在实际成员声明中使用过。
  • 我认为 OP 正在尝试这样做:fslang.uservoice.com/forums/245727-f-language/suggestions/… 不,这是不可能的。在您的示例中,foo.isZero(2) 有什么问题?

标签: f#


【解决方案1】:

如果您已经有实例的标识符,例如问题中的foo,则foo.isZero(2) |> ... 简短易读。在更长的管道中,使用 lambda 表达式:

funcThatReturnsMyClass(...) |> fun m -> m.isZero(2) |> Console.WriteLine

注意优先级;当事情变得复杂时,您可能希望在 lambda 周围添加括号,即|> (fun m -> ...) |>

如果这种情况经常出现,添加一些柯里化函数会有所帮助。这适用于实例成员以大写字母开头,而静态成员或 let-bound 函数以小写字母开头的约定。这样,如果您需要大量管道但又想支持点表示法,您可以定义这两种语法:

type MyClass2 (magicInt : int) =
    member __.IsMagic i = i = magicInt
    static member inline isMagic i (instance : MyClass2) = instance.IsMagic i

现在,您可以在实例上使用点表示法,也可以在管道上使用:|> MyClass2.isMagic 2 |> ...

isMagic 的实现可能看起来过度,但重点是无需额外费用即可转发到其他实现。这通常比复制实现要好,即使实现很短,因为它不会创建可能不同步、可能需要额外测试等的额外变体。

【讨论】:

    猜你喜欢
    • 2017-11-14
    • 2017-10-12
    • 2011-06-05
    • 1970-01-01
    • 1970-01-01
    • 2011-12-15
    • 2012-02-01
    • 1970-01-01
    相关资源
    最近更新 更多