我可以使用管道运算符的模块和静态成员函数的函数。我可以将它与非静态成员函数一起使用吗?
我的课程:
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#的清晰语法。
答案 0 :(得分:3)
如果您已经拥有该实例的标识符,例如问题中的foo
,则foo.isZero(2) |> ...
简短易读。在较长的管道内,使用lambda表达式:
funcThatReturnsMyClass(...) |> fun m -> m.isZero(2) |> Console.WriteLine
注意优先顺序;当事情变得复杂时,你可能想在lambda周围添加括号,即|> (fun m -> ...) |>
。
如果这种情况发生了很多,添加一些curried函数会有所帮助。这适用于实例成员以大写字母开头的约定,而静态成员或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
的实施可能看起来过多,但重点是转发到其他实施,而无需额外费用。这通常比复制实现更好,即使实现很短,因为它不会创建可能不同步的额外变体,可能需要额外的测试等等。