我在 F# 中有一个例子:
let a n = Convert.ToString(n:int32)
我可以说:
3 |> a
评估为"3"
。Ruby 中有类似的构造吗?
这是 F#(和其他 FP 语言)的方法链接,它不是函数组合,也不是 Ruby 中的方法链接,即返回 self 的对象,以便可以调用对象上的其他方法,如a.b.c.d
.
这在 Ruby 中很容易实现。直接取自 F# 参考文档:
let function1 x = x + 1
let function2 x = x * 2
let result = 100 |> function1 |> function2
//> val result : int = 202
这可以用 Ruby 编写如下:
function1 = -> x { x + 1 }
function2 = -> x { x * 2 }
result = 100.pipe(function1).pipe(function2)
# => 202
通过以下实现Object#pipe
:
class Object
def pipe(callable)
callable.(self)
end
end
或者用你的例子:
a = -> n { String(n) }
3.pipe(a)
# => '3'
和
let f x y = x * y
3 |> f(2)
// > 6
变成
f = -> (x, y) { x * y }
3.pipe(f.curry.(2))
# => 6
Ruby 不支持这种 F#/Ocaml/Haskel 表示法。虽然我相信你可以做点什么。但关键是你不应该。
如果你想以函数式的方式实现事物(这很棒),你可以使用Enumerable
ruby 提供的功能 - inject
、map
、select
等。
它将产生一个干净可读的 ruby 代码,没有任何黑客攻击。
PS:这个问题+1。当我第一次开始使用 ruby 时,我自己也问过这个问题。
没有这样的表示法,但您可以添加一个Object
传递self
给给定方法的方法。就像是:
class Object
def pass_to(m)
m.call(self)
end
end
这将允许这样的调用:
def convert_to_string(n)
n.to_s
end
def reverse_string(s)
s.reverse
end
123
.pass_to(method(:convert_to_string))
.pass_to(method(:reverse_string))
#=> "321"
或使用 lamdas:
convert_to_string = -> n { n.to_s }
reverse_string = -> s { s.reverse }
123
.pass_to(convert_to_string)
.pass_to(reverse_string)
#=> "321"
这相当于将to_s
消息发送到123
(返回"123"
),然后将reverse
消息发送到"123"
:
123
.to_s
.reverse
#=> "321"