【问题标题】:Ruby (NoMethodError) because of argument passingRuby (NoMethodError) 因为参数传递
【发布时间】:2015-10-07 12:37:13
【问题描述】:

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

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)

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

【问题讨论】:

    标签: ruby function variables nomethoderror


    【解决方案1】:

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

    def myfunction(num=3)
      num
    end
    
    varfunc = myfunction
    
    puts varfunc # it outputs 3 here, as expected
    

    这有几个问题。

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

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

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

    的东西
    #<Function:0xdeadbeef4815162342>
    

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

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

    但这并不容易......

    puts varfunc(12)
    

    给我这个控制台错误:

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

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

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

    有两种方法可以解决这个问题。一种方法是使 myfunction 成为 Proc 对象,这是 Ruby 最接近“函数”的等效对象:

    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
    

    另一种可能性是使用反射来获取myfunction 方法的Method 包装器对象,使用Object#method 方法:

    def myfunction(num=3) num end
    
    varfunc = method(:myfunction)
    
    puts varfunc
    # #<Method: Object#myfunction>
    
    puts varfunc.()
    # 3
    
    puts varfunc.(12)
    # 12
    

    【讨论】:

    • 非常感谢!相当说明性的答案。我试图做的是类似于 Python 的东西,我可以简单地将一个函数分配给一个变量,然后将它用作原始函数。带括号的事情是我读到在 Ruby 中你可以将它们排除在外并传递用逗号分隔的参数,所以我做到了。
    • 是的,完全正确,您可以省略括号,它会仍然调用该方法。括号是可选的。但是,在您的原始代码中,您两次 省略了括号,预计会发生两件不同 的事情:第一次您希望它像 Python 一样,其中括号是 required 用于调用并将它们关闭只是引用该函数。而第二次,您希望函数被调用 尽管 省略括号。换句话说,您的代码中的逻辑在内部是不一致的。追查这种不一致将......
    • ……最终引导你走上我(希望)现在引导你的发现之路。这是帮助您调试代码的通用工具:验证您的假设和内部逻辑。在这种情况下,您读到不需要括号来调用方法(这是正确的),同时您认为它会像 Python 一样工作(这与您阅读的内容相矛盾)。
    • 是的,你是对的。你的帖子对我很有帮助。带括号的东西,就像隐含的返回值一样,是我在学习 ruby​​ 时遇到的问题,因为我认为这些东西是不一致的,但是,这就是语言的方式,它们必须存在是有原因的。再次感谢
    猜你喜欢
    • 2014-04-09
    • 2015-04-07
    • 1970-01-01
    • 2015-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-01
    相关资源
    最近更新 更多