Ruby Print Inject Do Синтаксис - PullRequest
       27

Ruby Print Inject Do Синтаксис

30 голосов
/ 24 января 2010

Почему следующий код работает нормально

p (1..1000).inject(0) { |sum, i|
    sum + i
}

Но следующий код выдает ошибку

p (1..1000).inject(0) do |sum, i|
    sum + i
end

warning: do not use Fixnums as Symbols
in `inject': 0 is not a symbol (ArgumentError)

Разве они не должны быть эквивалентными?

Ответы [ 3 ]

36 голосов
/ 24 января 2010

Блок, написанный с помощью фигурных скобок, привязывается к методу ввода, который является вашим намерением, и он будет работать нормально.

Однако блок, инкапсулированный в блок do / end, будет привязан к p-методу. Из-за этого вызов inject не имеет ассоциированного блока. В этом случае inject будет интерпретировать аргумент, в данном случае 0, как имя метода для вызова каждого объекта. Bacuase 0 не является символом, который может быть преобразован в вызов метода, это приведет к предупреждению.

7 голосов
/ 24 января 2010

Проблема с p в начале. Если вы пропустите это, вы увидите, что оба работают нормально:

# Works!
[5, 6, 7].inject(0) do |sum, i| # Correctly binds to `inject`.
  sum + i
end

# Works too!
[5, 6, 7].inject(0) { |sum, i|  # Correctly binds to `inject`.
  sum + i
}

Но это не сработает:

# Kablammo! "p" came first, so it gets first dibs on your do..end block.
# Now inject has no block to bind to!
p [5, 6, 7].inject(0) do |sum, i|   # Binds to `p` -- not what you wanted.
  sum + i
end
6 голосов
/ 24 января 2010

Это похоже на эффект разницы в связывании между do / end и скобками:

скобки, используемые, как вы указали выше, будут привязаны к последней цепочке функций, а do / end - к ​​первой.

Я думаю, это своего рода странный способ сказать это, но в основном первый экземпляр передает блок в функцию 'inject', в то время как второй фактически пытается передать блок первому методу 'p'.

...