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
我正在尝试将一个函数分配给一个变量,这样做感觉很自然:
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