【问题标题】:Ruby do/end vs bracesRuby do/end vs 大括号
【发布时间】:2011-07-27 16:16:56
【问题描述】:

为什么这个 map 表达式会根据我使用大括号还是 do/end 产生不同的结果?

a = [1,2,3,4,5]


p a.map { |n|
    n*2
}  
#=> [2,4,6,8,10]


p a.map do |n|
    n*2
end  
#=> [1,2,3,4,5]

【问题讨论】:

标签: ruby block


【解决方案1】:

那是因为第二行被解释为:

p(a.map) do ... end

代替:

p(a.map do ... end)

在这种情况下,语法不明确,do 的绑定似乎不如 { 强。

【讨论】:

  • @Grandpa 这不是特别关于“p”。这是关于方法的参数/块和{}之间的强度/优先级,做结束
  • 如何才能将do...end 与多行块一起使用,以便map 将其作为参数?大括号 - 根据您的建议 - 不会这样做,Ruby 会抛出错误,unexpected keyword_do_block 甚至整个块都是一行。
  • @karatedog:你可能需要在这里使用一个中间变量,因为解析器不支持你想要的。
  • @DarkDust 谢谢,但当 Enumerator 无限时我不能使用中间变量,因为我必须事先知道我应该在该中间变量中生成多少项目。
  • 我不明白你的意思,当然你可以foo = a.map do ... end ; p(foo)。这是完全相同的语义,因为map 总是需要先聚合一个数组才能传递。然后将该数组存储在变量中或作为参数传递给另一个方法都没有区别,无论如何都需要先创建数组。
【解决方案2】:

这与{ 字符和do 关键字的关联性不同有关。

在第一种情况下,块被解释为map 函数的块参数。 map 函数的结果是p 函数的参数。

在第二种情况下,块被解释为p 函数的块参数,而a.map 被解释为p 函数的第一个参数。由于a.map 的计算结果为a,因此将打印原始数组。在这种情况下,该块实际上被忽略了。

【讨论】:

    【解决方案3】:

    使用do/end 语法,您将块作为第二个参数传递给p,而不是传递给地图。您会得到相同的结果:

    p a.map
    

    p 忽略该块,因为它不会在 inspect 上产生任何内容。

    【讨论】:

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