Ruby (NoMethodError) 因为参数传递

Ruby (NoMethodError) because of argument passing

我正在尝试将一个函数分配给一个变量,这样做感觉很自然:

def myfunction(num=3)
    num
end

varfunc = myfunction

puts varfunc # it outputs 3 here, as expected

但这并不容易...

puts varfunc(12)

给我这个控制台错误:

test.rb:8:in `<main>': undefined method `varfunc'
for main:Object (NoMethodError)

那怎么传递参数呢?非常感谢。

I'm trying to assign a function to a variable, it feels so natural to do this:

def myfunction(num=3)
  num
end

varfunc = myfunction

puts varfunc # it outputs 3 here, as expected

这有几个问题。

首先,myfunction不是一个函数,它是一个方法。 Ruby 中的方法不是对象。您只能将对象分配给变量,因此,由于方法不是对象,您不能将它们分配给变量。

其次,您没有将方法 myfunction 分配给变量 varfunc,因为正如我上面所解释的,您 不能 那样做。您正在 调用 方法 myfunction 并将其 return 值分配给变量 varfunc。在 Ruby 中,括号对于方法调用是可选的。

第三,即使 if 这个 did 也像你期望的那样工作,即 if方法是对象(它们不是),那么你展示的代码仍然不应该像你看到的那样工作。 如果 varfunc 一个函数,那么代码将不是 "output 3 here, as expected" ,因为你会期望 varfunc 是一个函数,而不是一个整数,它 应该 输出类似

#<Function:0xdeadbeef4815162342>

因此, 输出 3 是 预期的事实,事实上清楚地告诉您您的预期是 错误.

您的逻辑不一致:在第 5 行,您假设省略括号 不会 调用 myfunction,而是在第 7 行引用它,您假设去掉括号将 而不是 引用 varfunc,而是调用它。这毫无意义。

But it's not that easy...

puts varfunc(12)

Gives me this console Error:

test.rb:8:in `<main>': undefined method `varfunc'
for main:Object (NoMethodError)

How can arguments be passed then? Many thanks.

varfunc 是变量,不是方法。您只能将参数传递给方法,而不能传递给变量。您需要使 varfunc 成为一种方法。

有两种方法可以解决这个问题。一种方法是使 myfunction 成为 Proc 对象,它是 Ruby 最接近 "function":

的对象
myfunction = -> (num=3) { num }

varfunc = myfunction

puts varfunc
# #<Proc:0x007f909285f640@(irb):1 (lambda)>
# *This* is the output you would expect from `puts`ing a "function"

puts varfunc.()
# 3

puts varfunc.(12)
# 12

另一种可能是使用反射来获得一个Method wrapper object for the myfunction method, using the Object#method方法:

def myfunction(num=3) num end

varfunc = method(:myfunction)

puts varfunc
# #<Method: Object#myfunction>

puts varfunc.()
# 3

puts varfunc.(12)
# 12