1.8

2009-07-05 4 views
2
루비 1.8 (내 버전 1.8.7-72이다),이 코드에서

:1.8

foo = lambda do 
    for j in 1..2 
    return 
    end 
end 
foo.call 

충돌합니다 LocalJumpError와 :

test2.rb:3: unexpected return (LocalJumpError) 
    from test2.rb:2:in `each' 
    from test2.rb:2 
    from test2.rb:6:in `call' 
    from test2.rb:6 

왜 이 일을합니까? 그러나 Ruby 1.9 버전에서 정상적으로 실행되는 것으로 보입니다.

편집 : 그냥 람다 안에서 돌아 오는 것이 아닙니다. 다음은 정상적으로 실행됩니다 :

foo = lambda do 
    return 
end 
foo.call 

답변

8

람다의 중간에있는 for 문은 내부적으로 블록으로 변환됩니다. Ruby에서 블록 내부의 return 문은 그 둘러싸는 방법으로 범위가 지정됩니다. 다음을 고려하십시오 return 전체 bar 방법으로 범위가 있기 때문에

def bar 
    foo = lambda do 
    for j in 1..2 
     return j 
    end 
    end 
    foo[] 
end 
p bar 

bar를 실행 1이 반환됩니다. 블록을 반환하려면 next 또는 break을 사용하고 둘 다 매개 변수를 사용합니다. 다음을 고려하십시오.

def bar 
    foo = lambda do 
    for j in 1..2 
     break j 
    end 
    end 
    foo[] + 1 
end 
p bar 

이 중단은 사용자를 블록에서 반환하고 모든 후속 반복을 차단합니다. 이 경우 bar을 호출하면 반복자가 1을 반환하므로 foo[] + 12을 반환하므로 2을 반환합니다.

모든 것이 혼란 스럽다면, 블록 내부의 반환이 주변 방법으로 범위가 지정되고 주위 방법이 없으면 LocalJumpError이 발생한다는 사실을 깨닫는 것이 가장 중요합니다.

+0

왜 대신 람다 범위를 지정할 수 있습니까? 원래 시나리오에서는 건너 뛸 필요가있는 for 루프 다음에 코드가 있기 때문에 루프에서 벗어날 수는 없습니다 – user102008

+0

람다 대신 실제 메서드를 사용해 볼 수 있습니다. –

+0

젠장. Ruby 1.8은 define_method를 통해 정의 된 메소드 내부에서 proc 내부에서 리턴을 허용하지 않습니다. 그걸 긁어. –

0

당신은 또한 당신이 값을 반환하는 데 사용할 수있는 옵션 초 있었던 파라미터를 취 루프와 드로와 람다의 나머지/캐치

foo = lambda do 
     catch(:escape) do 
      for j in 1..2 
      throw :escape 
      end 
      # other code that won't get run 
     end # catch(:escape) 
     end # lambda 

throw을 피할 수 있습니다.

+0

이것은 수익을 모방하는 꽤 무거운 솔루션이라고 생각합니다. –

+0

다른 옵션은 예외이며 callcc 인 다른 반환 옵션을 사용할 수 없습니다. 나는 그것이 가장 가벼운 선택이라고 생각한다. 최선의 해결책은 아마 방법을 사용하는 것일뿐입니다. 그러나 당신이 끝내야하는 범위가 그 점에 잘 적응하지 못한다면 이것은 어색 할 수 있습니다. 그래서 1.9가 람다에서 돌아 오게하는 것이 좋습니다. –

+0

Ruby 1.8에서 Ruby 1.9 람다를 에뮬레이션하는 방법을 추가했습니다.이 대답은 throw/catch보다 가볍습니다. –

관련 문제