【问题标题】:Ruby curly braces vs. do-end method chainingRuby 花括号与 do-end 方法链接
【发布时间】:2013-12-06 13:11:50
【问题描述】:

我发现了一个问题:Nested Loops Ruby 并解决了它,但解决方案看起来很难看(虽然有效):

puts (1..10).map { |i| (i..10).step(i).inject(0) { |memo, obj| memo = memo | 2**(obj-1) } }.inject(0) { |memo, obj| memo = memo ^ obj}

重写为多行,但保留花括号:

puts (1..10).map { |i| 
    (i..10).step(i).inject(0) { |memo, obj| 
        memo = memo | 2**(obj-1)
        }
    }.inject { |memo, obj|
        memo = memo ^ obj
        }

我尝试将其重写为多行 do-end 块以使其更具可读性(了解 {}do-end 之间的优先级差异),但出现错误(我只是更改了最后一个大括号):

puts (1..10).map { |i| 
    (i..10).step(i).inject(0) { |memo, obj| 
        memo = memo | 2**(obj-1)
        }
    }.inject do |memo, obj|
        memo = memo ^ obj
        end.to_s(2)
../../bitflipping.rb:5:in 'each': 没有给出块 (LocalJumpError) 来自 ../../bitflipping.rb:5:in 'inject' 来自 ../../bitflipping.rb:5:in ''

可以用do-end 重写吗?我认为存在优先级问题,我该如何重新组合它们,例如最后的inject 可以正确获取块?

【问题讨论】:

  • map{|x| x} 毫无意义。
  • 没错,我刚刚删除了一些字符串到整数的转换,并且单个“x”保留了:-) 我编辑了这个问题。
  • 请注意,该错误说明了有关each 的内容,但each 不会出现在您的代码sn-p 中的任何位置。发布调用each 的代码。
  • @Kelvin:迭代器在内部使用each

标签: ruby method-chaining


【解决方案1】:

试着把它变成一种方法,也许吧?虽然正如sawa 所说,map{|x| x} 没有做任何事情

def my_method 
  first_step = (1..10).map do |i| 
    (i..10).step(i).map { |x| x}.inject(0) { |memo, obj| memo = memo | 2**(obj-1) }
  end
  second_step = first_step.inject { |memo, obj| memo = memo ^ obj}.to_s(2)
  return second_step
end

puts my_method

【讨论】:

  • 把它变成一个方法只是隐藏了问题:-)(也可以把它分成更小的部分)但我只想知道是否可以将大括号重写为 do-ends,如果可能的话,那么如何(在这种情况下)。
【解决方案2】:

触发问题的语法结构是不带括号的puts

您可以通过重构代码来解决此问题,以便首先将结果分配给变量(例如result),然后再执行puts result

另一种解决方案是将整个表达式括在括号中。

以下是场景的精简再现:

# OK, because assignment has lower precedence than do/end 
result = (1..10).inject do |memo, obj|
  memo + obj
end
puts result

# OK because the outer parentheses resolves the ambiguity
puts(
  (1..10).inject do |memo, obj|
    memo + obj
  end
)

# ERROR: no block given
puts (1..10).inject do |memo, obj|
  memo + obj
end

发生错误是因为 do/end 块的优先级低于方法调用(不带括号)。

ERROR 情况等价于:

puts( (1..10).inject ) do |memo, obj|
  memo + obj
end

...换句话说,您将块传递给puts,而不是inject。而inject(至少在这种情况下)失败了,因为它需要一个块。

【讨论】:

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