[ruby] 람다 사용시기, Proc.new 사용시기

Ruby 1.8에서는 proc / lambda와 다른 한편에 미묘한 차이가 Proc.new있습니다.

  • 그 차이점은 무엇입니까?
  • 어느 것을 선택할지 결정하는 방법에 대한 지침을 줄 수 있습니까?
  • Ruby 1.9에서는 proc과 lambda가 다릅니다. 거래는 무엇입니까?


답변

로 만든 발동 사이의 또 다른 중요하지만 미묘한 차이 lambda로 작성 발동은 Proc.new그들이 처리하는 방법입니다 return문 :

  • – 작성된 lambdaproc에서 return명령문은 proc 자체에서만 리턴합니다.
  • A의 Proc.new-created 시저의 return문은 조금 더 놀라운 일이다 : 그것은 단지 PROC에서하지 제어를 반환 뿐만 아니라 시저를 둘러싸는 방법에서!

여기에 lambdaproc이 생성 return되었습니다. 그것은 당신이 아마 기대하는 방식으로 행동합니다 :

def whowouldwin

  mylambda = lambda {return "Freddy"}
  mylambda.call

  # mylambda gets called and returns "Freddy", and execution
  # continues on the next line

  return "Jason"

end


whowouldwin
#=> "Jason"

이제 여기에 Proc.new생성 된 proc의 return동일한 작업이 있습니다. 루비가 가장 자랑스런 서프라이즈 원칙을 위반 한 사례 중 하나를 보려고합니다.

def whowouldwin2

  myproc = Proc.new {return "Freddy"}
  myproc.call

  # myproc gets called and returns "Freddy", 
  # but also returns control from whowhouldwin2!
  # The line below *never* gets executed.

  return "Jason"

end


whowouldwin2         
#=> "Freddy"

이 놀라운 행동 (타이핑이 적음) 덕분에 나는 procs를 만들 때 lambdaover를 사용하는 것을 선호 Proc.new합니다.


답변

추가 설명을 제공하려면 다음을 수행하십시오.

Joey는의 복귀 행동 Proc.new이 놀랍다 고 말합니다 . 그러나 Proc.new가 블록처럼 동작한다고 생각할 때 이것이 블록이 동작하는 방식과 마찬가지로 놀라운 것은 아닙니다. 반면에 lambas는 메소드와 비슷하게 동작합니다.

이것은 실제로 procs가 arity (논쟁 수)에 관해서 융통성이있는 이유를 설명하지만 람다는 그렇지 않습니다. 블록은 모든 인수를 제공 할 필요는 없지만 메소드가 제공합니다 (기본값이 제공되지 않는 한). 람다 인수 기본값을 제공하는 것은 Ruby 1.8에서 옵션이 아니지만, 이제 Ruby 1.9에서 대체 람다 구문을 사용하여 지원됩니다 (webmat에서 알 수 있음).

concat = ->(a, b=2){ "#{a}#{b}" }
concat.call(4,5) # => "45"
concat.call(1)   # => "12"

그리고 Michiel de Mare (OP)는 Ruby 1.9에서 Arity와 동일하게 동작하는 Procs와 lambda에 대해 올바르지 않습니다. 위와 같이 여전히 1.8에서 동작을 유지한다는 것을 확인했습니다.

break진술은 실제로 Procs 또는 람다에서별로 의미가 없습니다. Procs에서는 휴식이 이미 완료된 Proc.new에서 돌아옵니다. 람다가 본질적으로 방법이기 때문에 람다에서 벗어나는 것은 의미가 없으며, 최상위 수준의 방법에서 결코 벗어나지 않을 것입니다.

next, redoraiseProcs와 lambdas에서 동일하게 작동합니다. 반면 retry어느 쪽도 허용되지 않으며 예외가 발생합니다.

마지막으로이 proc방법은 일관성이없고 예상치 못한 동작이 있으므로 사용해서는 안됩니다. Ruby 1.8에서는 실제로 람다를 반환합니다! Ruby 1.9에서는이 문제가 해결되었으며 Proc을 반환합니다. Proc을 만들려면을 사용하십시오 Proc.new.

자세한 내용 은이 정보의 대부분을 제공하는 O’Reilly의 The Ruby Programming Language 를 적극 권장 합니다.


답변

차이점 과 차이점을 보여주는 이 페이지 를 찾았습니다 . 페이지에 따르면 유일한 차이점은 람다는 허용되는 인수 수에 대해 엄격한 반면 누락 된 인수는로 변환한다는 것 입니다. 차이점을 설명하는 IRB 세션의 예는 다음과 같습니다.Proc.newlambdaProc.newnil

irb (main) : 001 : 0> l = 람다 {| x, y | x + y}
=> # <Proc : 0x00007fc605ec0748 @ (irb) : 1>
irb (main) : 002 : 0> p = Proc.new {| x, y | x + y}
=> # <Proc : 0x00007fc605ea8698 @ (irb) : 2>
irb (main) : 003 : 0> l.call "hello", "world"
=> "helloworld"
irb (main) : 004 : 0> p.call "hello", "world"
=> "helloworld"
irb (main) : 005 : 0> l. "hello"전화
ArgumentError : 잘못된 개수의 인수 (1/2)
    부터 (irb) : 1
    (irb) : 5 :`call '에서
    에서 (irb) : 5
    : 0에서
irb (main) : 006 : 0> p.call "hello"
TypeError : nil을 문자열로 변환 할 수 없습니다
    from (irb) : 2 : in`+ '에서
    에서 (irb) : 2
    (irb) : 6 :`call '에서
    에서 (irb) : 6
    : 0에서

오류 허용 동작을 구체적으로 원하지 않는 한이 페이지에서는 람다 사용을 권장합니다. 이 정서에 동의합니다. 람다를 사용하는 것은 조금 더 간결한 것처럼 보이며, 그와 같은 의미없는 차이로 인해 평균 상황에서 더 나은 선택 인 것 같습니다.

루비 1.9에 관해서는, 미안하지만, 아직 1.9를 보지 않았지만 그들이 그렇게 많이 바꿀 것이라고는 생각하지 않습니다 (그러나 내 말을하지 마십시오. 나는 아마도 틀렸다.)


답변

Proc는 나이가 많지만 리턴의 의미는 (최소한 언어를 배우고있을 때) 나에게 반 직관적입니다.

  1. proc을 사용한다면, 아마도 일종의 기능적 패러다임을 사용할 것입니다.
  2. Proc는 기본적으로 진행되며 기능이 거의없는 엔 클로징 범위 (이전 응답 참조)에서 벗어날 수 있습니다.

Lambda는 기능적으로 안전하고 추론하기 쉽습니다. 저는 항상 proc 대신 사용합니다.


답변

미묘한 차이점에 대해서는 많이 말할 수 없습니다. 그러나 Ruby 1.9는 이제 람다 및 블록에 대한 선택적 매개 변수를 허용합니다.

1.9 이하의 스테이 비 람다에 대한 새로운 구문은 다음과 같습니다.

stabby = ->(msg='inside the stabby lambda') { puts msg }

루비 1.8에는 그런 문법이 없었습니다. 블록 / 람다를 선언하는 기존의 방법은 선택적 인수를 지원하지 않았습니다.

# under 1.8
l = lambda { |msg = 'inside the stabby lambda'|  puts msg }
SyntaxError: compile error
(irb):1: syntax error, unexpected '=', expecting tCOLON2 or '[' or '.'
l = lambda { |msg = 'inside the stabby lambda'|  puts msg }

그러나 Ruby 1.9는 이전 구문에서도 선택적 인수를 지원합니다.

l = lambda { |msg = 'inside the regular lambda'|  puts msg }
#=> #<Proc:0x0e5dbc@(irb):1 (lambda)>
l.call
#=> inside the regular lambda
l.call('jeez')
#=> jeez

Leopard 또는 Linux 용 Ruby1.9를 빌드하려면 이 기사 (shameless self promotion)를 확인하십시오.


답변

짧은 대답 : 중요한 것은 무엇입니까? return람다는 자체를 반환하고 proc은 자체를 반환하고 함수를 호출합니다.

덜 명확한 것은 각각을 사용하려는 이유입니다. 람다는 기능적 프로그래밍 의미에서해야 할 일입니다. 기본적으로 현재 범위가 자동으로 바인딩되는 익명의 방법입니다. 둘 중 람다는 아마도 사용해야 할 것입니다.

반면 Proc는 언어 자체를 구현하는 데 실제로 유용합니다. 예를 들어 “if”문 또는 “for”루프를 구현할 수 있습니다. proc에서 발견 된 모든 리턴은 단지 “if”문이 아니라 호출 한 메소드에서 리턴됩니다. 이것은 언어가 작동하는 방식, “if”문이 작동하는 방식입니다. 그래서 루비는 이것을 커버 아래에서 사용하고 강력 해 보였기 때문에 그냥 노출했습니다.

루프, if-else 구문 등과 같은 새로운 언어 구문을 생성하는 경우에만 필요합니다.


답변

그것을 보는 좋은 방법은 람다는 자신의 범위에서 (메소드 호출 인 것처럼) 실행되는 반면 Procs는 호출 메소드와 함께 인라인으로 실행되는 것으로 볼 수 있습니다. 적어도 하나를 사용할 것을 결정하는 좋은 방법입니다 각각의 경우에.