2010-01-24 3 views
28

이유는 다음 코드루비 인쇄를 주입 할 일 구문

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) 

가 동등하지 않나요을 제공 잘 실행하는 것이 그 것이다?

답변

34

중괄호를 사용하여 작성된 블록은 사용자의 의도와 일치하는 삽입 방법에 바인딩되며 정상적으로 작동합니다.

그러나 do/end 블록에 캡슐화 된 블록은 p-method에 바인딩됩니다. 이 때문에 inject 호출에는 연관된 블록이 없습니다. 이 경우 inject는 모든 객체에서 호출 할 메소드 이름으로 인수 (이 경우 0)를 해석합니다. Bacuase 0은 메소드 호출로 변환 할 수있는 심볼이 아니므로 경고를 표시합니다.

6

이 할 일/끝 괄호 사이의 바인딩의 차이의 효과 다음과 같습니다 위에서 그대로 사용

브라켓, 체인 동안 처음에 바인딩/종료 할 마지막 기능에 결합합니다.

나는 그것을 말하는 이상한 방법이라고 생각하지만 기본적으로 첫 번째 인스턴스는 블록을 'inject'함수에 전달하는 반면 두 번째는 실제로 블록을 첫 번째 메소드 'p'에 전달하려고합니다.

+1

"두 번째는 실제로 첫 번째 방법으로 블록을 전달할 시도하는 동안 (1 ..1000). " 그것을 "첫 번째 메소드'p'로 만들면 올바른 것입니다. – sepp2k

+0

나는 그것을 바로 잡았다. 첫눈에 위의 코드에서 간과했다! – Pete

6

문제는 처음에는 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 
관련 문제