2016-07-04 3 views
2

왜 그것을입니다 :내 블록이 한 번만 실행되는 이유는 무엇입니까?

array = (1..20).to_a 
array.index.each_slice(5) do |slice| 
    puts slice.inspect 
end 

반환 :

[1, 2, 3, 4, 5] 
[6, 7, 8, 9, 10] 
[11, 12, 13, 14, 15] 
[16, 17, 18, 19, 20] 

동안 : 만

other_array = [] 
array = (1..20).to_a 
array.index.each_slice(5) do |slice| 
    puts slice.inspect 
    other_array.push(1) 
end 

반환 : other_array.push(1) 휴식 전을 수행하는 방법

[1, 2, 3, 4, 5] 

블록의 생태? 분명한 결론은 블록 범위에 속하지 않는 변수에 액세스 할 수 없다는 것입니다.하지만 그 이유는 무엇입니까?

+1

실제로'index'를 호출하는 것이 보이지 않는다. (이것은 배열 푸시가 아닌) – Vasfed

+1

문서에''''index''라고 쓰여있다. "블록이나 인수가 주어지지 않을 때 열거자를 반환합니다."그래서 나는''index''를 호출했습니다. each_slice를 호출 할 수 있도록 열거자를 필요로했지만. 이제는 Array에 Module Enumerable이 포함되어 있으므로 each_slice 메서드 자체가 있습니다. –

+0

이것을 보는 한 가지 방법은'enum1 = array.index # => # ; enum2 = enum1.each_slice (5) # => # <열거 자 : # <열거 자 : [1, .. 20] : 색인> : each_slice (5)>'. 이 반환 값을주의 깊게 조사하십시오. 'enum2'를 "복합"열거 자라고 생각하면됩니다. 'enum2'가 생성 한 요소를'enum2.to_a # => [[1, ... 5], ... [16, ... 20]]'배열로 변환하여 볼 수 있습니다. 그리고 나서'enum2.each {| slice | slice.inspect} # => [1, ... 5] ... [16, ... 20]'을 넣습니다. 눈치 챘 겠지만,'.index'가 생략되면 같은 결과를 얻는다. –

답변

6

배열 설명서에서 해결책을 찾았습니다. 배열에 대해 반복 할 때 배열에 대해 index 함수를 사용하는 이유가 궁금했습니다. 이를 위해 인덱스 호출없이 array.each_slice을 사용할 수 있습니다. http://ruby-doc.org/core-2.2.0/Array.html#method-i-index

개체가 obj와 ==되도록 워의 첫 번째 개체의 인덱스를 돌려줍니다 인덱스는 다음과 말했다.

인수 대신 블록을 지정하면 블록이 true를 반환하는 첫 번째 개체의 인덱스를 반환합니다. 일치하는 항목이 없으면 nil을 반환합니다.

따라서 코드는 블록을 평가하고 결과가 true인지 확인합니다. 첫 번째 예에서는 nil을 반환하는 puts 만 수행합니다. Nil은 거짓입니다.
두 번째 예는 단일 1을 포함하는 배열의 객체를 반환합니다.
루비에서 모든 조건은 true이고 false 또는 nil이 아닌 경우입니다. 당신은 여기를 볼 수 있습니다 다시 실행되지 않도록

if nil 
    puts "foo" 
end 
=> nil 

other_array = [1] 
if other_array 
    puts "foo" 
end 
=> "foo" 

그래서 두 번째 예에서 블록이 거짓없는 뭔가를 반환, 그것은 "유효"결과를 찾을 수 있기 때문이다.

반환을 위해, 다른 반환 값이 주어지지 않으면 ruby가 모든 범위의 마지막 표현식을 반환한다는 것을 알아야합니다. 따라서 other_array을 반환합니다. 다음에 당신이 할 수 코드를 포맷하지 않으려면 :

other_array = [] 
array = (1..20).to_a 
array.index.each_slice(5) do |slice| 
    puts slice.inspect 
    other_array.push(1) 
    nil 
end 

nil를 반환하는 블록을 강제하고 반복 작동합니다.

+0

버그와 더 비슷합니다. 블록은'each_slice (5)'에 연결되어 있으므로'index' 호출의 동작에 영향을 주어서는 안됩니다. 게다가 블록이'index' 호출에 묶여 있다면 첫 번째 요소 인'1'을 반환해야하고'1'에'each_slice'를 호출하면 에러가 발생합니다. –

+0

오, 네 말이 맞아. 나는 그것을 보지 못했다. 'index.each_slice'가 실제로 작동하는 것이 이상합니다. 이 작업을 수행하려면 index가 배열을 반환해야합니다. – 0xAffe

+1

문서에'''index'''는 "블록이나 인자가 없을 때 열거자를 반환합니다"라고되어 있는데, 이것이 내가'''index''를 호출 한 이유입니다. each_slice를 호출 할 수 있도록 열거자를 필요로했지만. 이제는 Array에 Module Enumerable이 포함되어 있으므로 each_slice 메서드 자체가 있습니다. –

2

그것은 첫눈에 까다로운 것 같다,하지만 당신은 Array#index 의 문서를 확인하면이 방법 반환 Enum 더 블록이 제공하지 않는 경우는 것을 볼 수 있습니다.첫 번째 경우에

:

그런 다음 당신은 블록이 Enum 객체에 #each_slice(n) 전화

do |slice| 
    puts slice.inspect 
end 

#index 방법마다 nil 반환합니다. 당신이 두 번째에 array.index.each_slice(5) { nil } 또는

를 호출하면 동일한 결과를 얻을 수 있습니다 :이 블록의

do |slice| 
    puts slice.inspect 
    other_array.push(1) 
end 

값이 #index 방법에 [1]를 블록 내부 평가 반환하기 때문에 첫 번째 조각을 반환 배열의. 전화를 걸면 똑같은 결과가 나올거야 array.index.each_slice(5) { any_non_falsy_object }

관련 문제