5

为了理解 ruby​​ 的函数式编程部分,我想编写一个函数,它将 2 个函数 f(x,y),g(x) 作为参数并返回一个新函数 h(x,y)=f(g(x ),g(y))。

def foo(x, y)
    return x+y
end

def bar(x)
    return 2*x
end

def comp(f,g)

end

f=comp(f,g)
f(1,2) #=> 6

我尝试过类似的事情

def comp(f,g)
    mylambda = lambda {|x,y| return f(g(x),g(y))}
    return mylambda
end
f=comp(foo, bar)
f.call(1,2)

我认为 f 现在会成为 Proc,我可以直接调用它。但显然“在'foo'中:错误数量的参数(0代表2)(ArgumentError)”

我必须使用什么语法?是否有可能返回一个“真正的”函数而不是 Proc,这样我就可以像正常地定义 f 一样而不是 f.call(1,2) 来旋转 f(1,2) ?

4

5 回答 5

7

这种类型的函数式模式不像在更多函数式语言(如 javascript 或 python)上那样顺利运行。由于 ruby​​ 有可选的括号,因此编写与不传递任何参数而foo调用方法相同。foo

要获取对方法的引用,您需要使用该Object#method方法:

def foo(x, y)
  x + y
end

def bar(x)
  x * 2
end

def comp(f, g)
  lambda { |x, y| f.call(g.call(x), g.call(y)) }
end

h = comp(method(:foo), method(:bar))
h.call(1, 2) # => 6
于 2013-11-05T22:23:14.107 回答
2

Ruby 没有像 Python 这样的一流函数。Ruby 有 lambdas 和可以从方法专门构造的方法对象,但方法本身不是对象。你最接近这个的是:

def foo(x, y)
    return x+y
end

def bar(x)
    return 2*x
end

def comp(f,g)
  return lambda {|x, y| f.call(g.call(x), g.call(y))}
end

f=comp(method(:f),method(:g))
f.call(1,2) #=> 6

此外,对于调用语法点,您可以使用方括号调用 lambda,因此您可以这样做:

f[1,2]
于 2013-11-05T22:21:03.580 回答
2

你所拥有的不是函数,它们是方法。函数(更准确地说:过程)定义如下:

foo = -> (x, y) { x + y }

bar = -> x { 2 * x }

comp = -> (f, g) { -> (x, y) { f.(g.(x), g.(y)) } }

f = comp.(foo, bar)

f.(1, 2) #=> 6
于 2013-11-05T23:06:04.617 回答
2

尝试这个:

def foo() lambda {|x,y| x+y} end
def bar() lambda {|x| 2*x} end
def comp(f,g) lambda {|x,y| f[g[x], g[y]]} end
h = comp(foo, bar)
h[1,2]       # => 6

或以下任何一项

h.call(1,2)  # => 6
h.(1,2)      # => 6
h.yield(1,2) # => 6

如果你愿意,

foo = lambda {|x,y| x+y}
bar = lambda {|x| 2*x}

在这个问题之前,我不知道现在可以调用 lambda(或 proc)的无数方法。(提供的理由让我无法理解,因为它与我们都知道和喜爱的不相关的关键字Proc#yield相同call并且可能会混淆。)可以替换or ,或使用“stabby”语法创建 lambda (例如,.yieldProc.newproclambda->def bar() ->(x) {2*x} end

于 2013-11-05T22:19:48.583 回答
0
f=comp(foo, bar)

这不会像在 python 中那样工作。您收到的错误消息是希望看到这样的内容。

f = comp(foo(1,2), bar(1))

如果您想这样调用它,您需要实际制作foo和lambdas 自己(或返回 lambdas 的方法):bar

foo = lambda { |x, y| x + y }
bar = lambda { |x| 2 * x }

or

def foo(x, y)
  lambda { |x, y| x + y}
end

def bar(x)
  lambda { |x| 2 * x }
end

然后你就可以实现你想做的事情。

于 2013-11-05T22:12:22.633 回答