【问题标题】:What order are method arguments evaluated in Ruby?Ruby 中方法参数的求值顺序是什么?
【发布时间】:2016-03-24 17:58:57
【问题描述】:

直到my attempt 回答this question,我一直认为参数是按照我们输入它们的方式从左到右进行评估的。例如我们有一些方法:

def foo(a,b,c)

有没有办法在 Ruby 程序中随着时间的推移监控变量定义和值?如果你调用foo 0,1,2,你如何证明变量按以下顺序赋值?

时间 0:a = 0

时间1:b = 1

时间 2:c = 2

我意识到我的示例是微不足道的,因为我对 a, b, c 有相同类型的参数,但是当您引入默认参数、关键字参数和数组参数时,它可能会变得混乱。如果没有人知道答案,我将不胜感激有关如何确定答案的建议。

基本上是 this 的 Ruby 等价物。

【问题讨论】:

  • 这太疯狂了...我在 Google 上搜索了“ruby call what order are arguments”,最后到这里才发现你链接到我 4 年前的问题。仅供参考,我认为您在谈论参数分配顺序而不是参数分配。 stackoverflow.com/questions/156767/…

标签: ruby


【解决方案1】:

ISO Ruby 语言规范规定,参数按照它们在程序文本中出现的顺序绑定到参数。但是,规范对于这是否也意味着它们是按该顺序评估含糊不清。

RubySpec,AFAICS 根本没有说明方法参数的评估顺序。

因此,答案似乎是:方法参数没有保证的评估顺序。不同实现之间可能不同,同一实现的不同版本之间可能不同,同一实现的同一版本的两次运行之间可能不同,甚至对同一方法的两次调用之间可能不同。它们可以并行评估。

你只是不知道。

【讨论】:

  • 不知道最终订单有点令人沮丧,但你是对的。即使您可以使用一些代码显示在一个示例中它是/不是从左到右的,但这并不意味着它一定会始终如此。如果没有官方来源,我想我们无法知道。
  • 我可以肯定地说,在所有 ruby​​ 版本中(从 ruby​​1.8.6 到现在的 2.7.0),评估都是一样的。通过在rvm use [ruby version] && ruby -ve 'def m(x,y); {same: x==y, ltor: x<y, rtol: x>y}; end; p m(Time.now, Time.now) 下为迄今为止的所有 ruby​​ 版本(ruby 2.7.0)运行以下脚本,您将在{:same=>false, :ltor=>true, :rtol=>false} 下方获得以下返回值,其中same 表示同时评估 x 和 y,@ 987654325@ 表示从左到右,rtol 表示从右到左。
  • @PaaYaw 抱歉,但似乎问题是使用“参数”这个词,而从示例中 Op 清楚地表示“参数”。
  • @MikeS:规范指定某些内容是完全正常的。这实际上是性能的来源:不指定某些内容允许实现者选择最有效的选项。例如,在具有低开销的大型多核系统中,可以并行评估参数。指定评估顺序将拒绝此优化机会。
【解决方案2】:
def arg_test(a=Time.now, b=Time.now)
  puts "left to right" if a < b
end

arg_test #=> left to right

【讨论】:

  • 如果返回nil,这种方法将是不确定的。因为这可能意味着 b 要么首先分配,要么与 a 具有相同的时间戳。
  • 你可以只输出时间戳
【解决方案3】:

也许你可以记录对象的初始化,然后在堆栈中看到它们。

module Record
  @@stack = []
  def initialize *; super; @@stack.push(self) end
  def self.stack; @@stack end
end

class String
  prepend Record
end

def foo a, b, c; end

foo(String.new("x"), String.new("y"), String.new("z"))
Record.stack # => ["x", "y", "z"]

在这种情况下,abc 按此顺序进行评估。

使用默认值,可以看到:

def foo a, b, c = String.new("c"); end

foo(String.new("x"), String.new("y"))
Record.stack # => ["x", "y", "c"]

【讨论】:

  • 哦,这真是该死的天才。我要玩这个。
【解决方案4】:

对于任何来这里寻找参数分配顺序(问题在我发帖时提出的问题)而不是参数分配顺序的人。我一直认为它们是按照编写的顺序进行评估的,直到我尝试编写一些奇怪的代码并得到一个奇怪的结果。 steenslag 让我知道了如何测试它:

def arg_test(a, b)
  puts([a, b].inspect '- out of order!') if a > b
end

1000000.times {
  arg_test(Time.now, Time.now)
}

这导致没有输出。所以看起来它们是按顺序分配的,而我的其他代码可能只是有一个错误。

【讨论】:

    猜你喜欢
    • 2019-01-28
    • 1970-01-01
    • 2019-06-16
    • 1970-01-01
    • 2022-12-06
    • 1970-01-01
    • 2013-10-31
    • 1970-01-01
    • 2012-02-26
    相关资源
    最近更新 更多