为什么Ruby中的currying无法在我的代码中工作?

时间:2014-03-30 22:02:11

标签: ruby currying

我收到一条错误消息" method_object.rb:8:在`':错误的参数类型Fixnum(expect Proc)(TypeError)"尝试运行以下脚本时

def f(x,y=2)
  x**y
end

a=method(:f).to_proc  
b=a.curry.curry[4]

print 1.upto(5).map(&b)    
puts

但是,如果以下列方式定义 function f ,则一切正常。

def f(x,y)
  x**y
end

我的第一个代码出了什么问题会有人帮我吗?

2 个答案:

答案 0 :(得分:5)

Proc#curry

  

返回curried的proc。如果给出了可选的arity参数,则它确定参数的数量。 curried proc会收到一些参数。如果提供了足够数量的参数,它会将提供的参数传递给原始proc返回结果。否则,返回另一个带有其余参数的curried proc。

现在来看你的代码:

def f(x, y=2)
  x**y
end

a = method(:f).to_proc  
b = a.curry.curry[4]
b.class # => Fixnum
b # => 16
print 1.upto(5).map(&b) 
# wrong argument type Fixnum (expected Proc) (TypeError)

立即查看文档 - curried proc收到一些参数。如果提供了一个有效数量*的参数,它会将提供的参数传递给原始proc返回结果

在您的代码中,当您执行a.curry时,它会返回 curried proc 。为什么?因为您的方法f一个可选的一个必需的参数,但您没有提供任何参数。现在你再次调用a.curry.curry[4],所以在前面的 curried proc 仍在等待至少一个参数,这次你使用curry[4]给它。现在,使用proc作为参数调用 curried 4, 2对象,并将其评估为Fixnum对象8并分配给b b不是proc对象,而是Fixnum对象。

现在,1.upto(5).map(&b)此处 - &b表示您正在告知将proc对象分配给b转换为块。但b未持有proc个对象,而是Fixnum对象8。所以Ruby 抱怨给你。

此消息来自错误的参数类型Fixnum(预期Proc)(TypeError)

现在来看你的第二部分代码。坚持,稍等!! : - )

看下面:

def f(x, y)
  x**y
end
a = method(:f).to_proc  
b = a.curry.curry[4]
b.class # => Proc
b # => #<Proc:0x87fbb6c (lambda)>
print 1.upto(5).map(&b) 
# >> [4, 16, 64, 256, 1024]

现在,您的方法f需要2个强制参数x, ya.curry,您没有通过任何内容,因此返回 curried proc 。再次a.curry.curry[4],哼哼你传递了一个必需的参数,即2中的4。所以再次返回 curried proc

现在1.upto(5).map(&b),与之前的b相同,需要proc,并且您满足了它的需要,因为现在b是proc个对象。 &b将其转换为以下块:

1.upto(5).map { |num| b.call(num) }

又输出为 - [4, 16, 64, 256, 1024]

<强>摘要

现在假设您定义了proc,如下所示:

p = Proc.new { |x, y, z = 2| x + y + z }

现在你要将p作为 curried proc 。所以你做了p.curry。请记住,在调用curry时,您没有通过任何 arity 。现在点是一个 curried proc 将等待评估并返回x + y + z的结果,除非并且直到你给它所需的所有必需参数来产生结果。

这意味着p.curry会为您提供 curried proc 对象,如果您执行p.curry[1](意味着您现在将值传递给x),那么得到了一个 curried proc 。现在,当您编写p.curry[1][2]时,您传递的所有必需参数(意味着您现在将值传递给y),因此现在将调用x + y + z

答案 1 :(得分:1)

您使用的是.map,它需要block类型proc。在您的第一种情况下b返回16y=2在使用2发送单个参数时使用默认值curry作为指数。 b返回16不是proc object,不能与.map一起使用。

Curry与proc sufficient arguments一起使用时,会执行原始proc并返回结果。在OP的第一个案例中发生了这种情况,curried proc传递了4作为唯一参数,默认y=2 in f(x, y=2)被使用并导致16作为返回值。 16 Fixnum不能与枚举器map方法一起使用。

Curry使用参数不足时返回proc。因此,在使用f(x, y)的情况2中,curried a仅传递一个参数,导致返回proc对象{|e| 4 ** e},并由map方法执行