【问题标题】:Code block passed to each works with brackets but not with 'do'-'end' (ruby)传递给每个作品的代码块使用括号但不使用'do'-'end'(ruby)
【发布时间】:2011-10-06 19:05:42
【问题描述】:

我最近开始学习 ruby​​,我了解到您可以使用具有这两种语法的代码块。但是我只是发现了一个我不明白的案例:

#my_hash is a hash in which the keys are strings and the values arrays, but dont think about the specifics fo the code

#if I run my code like this, it works perfectly

my_hash.each do |art|
  puts mystring.gsub(art[0]).each {
    art[1][rand(art[1].length) -1]
  }
end

#but if I use this, it prints "Enumerator"

my_hash.each do |art|
  puts mystring.gsub(art[0]).each do
    art[1][rand(art[1].length) -1]
  end
end

是因为你不能嵌套 do-end 对吗? 我正在使用 1.9

【问题讨论】:

标签: ruby


【解决方案1】:
puts mystring.gsub(art[0]).each do
  art[1][rand(art[1].length) -1]
end

在这里你调用了puts,没有括号,do ... end 指的是puts 方法,它对块不做任何事情并打印mystring.gsub(art[0]).each(带有Enumerator)。

{ ... } 使用最近的方法调用。变得丑陋,但你可以用do ... end

puts(mystring.gsub(art[0]).each do
  art[1][rand(art[1].length) -1]
end)

或者,更好的是,将结果放入一个变量中并打印该变量:

var = mystring.gsub(art[0]).each do
  art[1][rand(art[1].length) -1]
end
puts var

无论如何,each 不会更改对象,它只是迭代并返回对象本身。你可能想要map 方法,测试一下。

【讨论】:

  • 谢谢,非常有帮助。就我而言,我可以将对象修改为 .each,但我想这是因为我将它与 gsub 一起使用,对吧?
【解决方案2】:

在 Ruby 中嵌套 do/end 对是完全合法的,但您会遇到 { } 和 do/end 之间微妙的优先级问题。

您可以阅读更多关于 here 的信息。

【讨论】:

    【解决方案3】:

    扩展 Scott 的回复,并引用 Jim Weirich

    不同之处在于它们在运算符优先级表中的位置。 { } 绑定比 do/end 更紧密。例如:

    f g { }

    被解析为 f(g { }),其中大括号属于方法 g。另一方面,

    f g 结束

    被解析为 f(g) do end,其中大括号属于方法 f。仅当您省略括号并产生歧义时才有意义。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-27
      • 1970-01-01
      • 2020-10-21
      • 1970-01-01
      • 2011-01-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多