prosource

람다를 사용할 때, Proc.new를 사용할 때?

probook 2023. 6. 27. 22:22
반응형

람다를 사용할 때, Proc.new를 사용할 때?

1Ruby 1.8의 proc/lambda .Proc.new반면에

  • 그것들의 차이점은 무엇입니까?
  • 어떤 것을 선택할지 어떻게 결정해야 하는지 가이드라인을 줄 수 있습니까?
  • Ruby 1.9에서는 proc와 람다가 다릅니다.무슨 일입니까?

로 생성된 프로시저 간의 또 다른 중요하지만 미묘한 차이lambda로 생성된 및 Proc.new그것이 그들이 처리하는 방법입니다.return문:

  • lambda proc, proc,return만 반환합니다.
  • Proc.new proc, proc,return진술은 조금 더 놀랍습니다: 그것은 단지 프로시저뿐만 아니라 프로시저를 둘러싸는 방법에서도 통제력을 반환합니다!

»lambda proc -created proc's -created proc.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 -created proc's -created 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"

이 놀라운 행동 덕분에 (타자를 덜 치는 것뿐만 아니라) 사용하는 것을 선호하는 경향이 있습니다.lambda1파운드가 Proc.new프록스를 만들 때.

추가 설명 제공:

조이가 말하기를 그들의 귀환 행동은Proc.new.할 때 이것은 . 이 정확히 동작하기 입니다. 메서드와 더 합니다.그러나 Proc.new가 블록처럼 동작한다는 것을 고려할 때 이것은 놀라운 일이 아닙니다. 블록이 정확히 그렇게 동작하기 때문입니다. 반면에 lambas는 메서드와 더 유사하게 동작합니다.

이것은 실제로 Procs가 배열(인수 수)에 있어서 유연한 반면, 람다는 그렇지 않은 이유를 설명합니다.블록은 모든 인수를 제공할 필요가 없지만 메서드는 제공합니다(기본값이 제공되지 않은 경우).Ruby 1.8에서는 람다 인수 default를 제공하는 것이 옵션이 아니지만, 이제 Ruby 1.9에서는 대체 람다 구문을 사용하여 지원됩니다(webmat에서 언급됨).

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

그리고 Michiel de Mare(OP)는 Procs와 람다가 Ruby 1.9에서 동일하게 동작한다는 것에 대해 올바르지 않습니다.나는 그들이 위에 명시된 대로 1.8부터의 동작을 여전히 유지하는 것을 확인했습니다.

break진술은 실제로 Procs나 Lambdas에서 별로 의미가 없습니다.Procs에서는 이미 완료된 Proc.new에서 휴식 시간이 반환됩니다.람다에서 분리하는 것은 말이 안 됩니다. 람다는 본질적으로 하나의 방법이기 때문입니다. 그리고 여러분은 하나의 방법의 최상위 단계에서 절대로 분리하지 않을 것이기 때문입니다.

next,redo,그리고.raise프록스와 람다 모두에서 동일하게 행동합니다.에 반에면.retry둘 다 허용되지 않으며 예외가 발생합니다.

그고마지로으막리,로▁and으,proc메서드가 일관되지 않고 예기치 않은 동작을 하므로 메서드를 사용하면 안 됩니다.Ruby 1.8에서는 실제로 람다를 반환합니다!Ruby 1.9에서 이것은 수정되었고 Proc를 반환합니다.Proc를 생성하려면 다음을 수행합니다.Proc.new.

더 많은 정보를 위해, 저는 이 정보의 대부분을 제공하는 오라일리의 루비 프로그래밍 언어를 강력히 추천합니다.

나는 이 페이지를 찾았는데, 이 페이지는 무엇이 다른지 보여줍니다.Proc.new그리고.lambda, 람다는 인수의 수에 대해 엄격하다는 한 차이점입니다.Proc.new를 누된인수로변를니합으로 합니다.nil다음은 차이를 보여주는 IRB 세션의 예입니다.

irb(주):001:0> l = 람다 { |x, y | x + y }=> #<Proc:0x00007fc605ec0748@(irb):1>irb(메인):002:0> p = Proc.new { |x, y | x + y }=> #<Proc:0x00007fc605ea8698@(irb):2>irb(메인):003:0> l.call "안녕하세요", "세계"=> "안녕하세요"irb(메인):004:0> p.call "안녕하세요", "세계"=> "안녕하세요"irb(메인):005:0> l.call "안녕하세요"인수 오류: 잘못된 인수 수(2의 경우 1)출처(irb):1from(irb):5: 'call'에서출처(irb):5:0부터irb(메인):006:0> p.call "안녕하세요"유형 오류: nil을 문자열로 변환할 수 없습니다.출처(irb):2: '+'에서출처(irb):2from(irb):6:in 'call'출처(irb):6:0부터

오류 허용 동작을 특별히 원하지 않는 한 람다를 사용하는 것이 좋습니다.저는 이 의견에 동의합니다.람다를 사용하는 것이 조금 더 간결한 것처럼 보이며, 이러한 사소한 차이로 인해 평균적인 상황에서 더 나은 선택인 것 같습니다.

루비 1.9에 대해서는, 미안하지만, 아직 1.9를 조사하지 않았지만, 그들이 그것을 그렇게 많이 바꾸지는 않을 것이라고 생각합니다. (하지만 제 말을 믿지 마세요, 당신이 약간의 변화에 대해 들은 것 같아서, 제가 거기서 틀렸을 수도 있습니다.)

Proc는 오래되었지만 반환의 의미는 다음과 같은 이유로 (적어도 언어를 배울 때) 매우 직관적이지 않습니다.

  1. proc를 사용하는 경우 기능 패러다임을 사용할 가능성이 높습니다.
  2. Proc는 기본적으로 수행해야 하는 작업으로, 본질적으로 매우 비기능적인 작업입니다(이전 응답 참조).

람다는 기능적으로 더 안전하고 추론하기 쉽습니다. 저는 항상 proc 대신에 그것을 사용합니다.

저는 미묘한 차이에 대해 많은 것을 말할 수 없습니다.하지만 Ruby 1.9는 이제 lamdas와 block에 대한 선택적 매개 변수를 지적할 수 있습니다.

다음은 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용 Ruby 1.9를 구축하고 싶다면 이 기사(뻔뻔한 자기 홍보)를 확인하십시오.

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

단답:중요한 것은 무엇입니까?returndoes: 람다는 자체에서 반환되고 proc는 자체 및 호출한 함수에서 반환됩니다.

덜 명확한 것은 왜 각각을 사용하려고 하느냐입니다. 람다는 기능적 프로그래밍의 의미에서 우리가 기대하는 것입니다.기본적으로 현재 범위가 자동으로 바인딩된 익명 메서드입니다.둘 중 람다를 사용해야 할 수도 있습니다.

반면 Proc는 언어 자체를 구현하는 데 매우 유용합니다.예를 들어 "if" 문 또는 "for" 루프를 구현할 수 있습니다.프로세스에서 발견된 모든 반환은 단순히 "if" 문이 아니라 호출된 메서드에서 반환됩니다.이것이 언어가 작동하는 방식이고, "만약" 문장이 작동하는 방식입니다. 그래서 제 추측으로는 루비가 이것을 위장해서 사용하고 그들은 그것이 강력해 보였기 때문에 그것을 노출했을 것입니다.

루프, if-else 구조 등과 같은 새로운 언어 구조를 만드는 경우에만 필요합니다.

저는 퀘스톤의 세 번째 방법인 "proc"에 대한 언급을 보지 못했습니다. "proc"는 사용되지 않지만 1.8과 1.9에서 다르게 처리되었습니다.

다음은 유사한 세 가지 호출 간의 차이를 쉽게 확인할 수 있는 상당히 자세한 예입니다.

def meth1
  puts "method start"

  pr = lambda { return }
  pr.call

  puts "method end"  
end

def meth2
  puts "method start"

  pr = Proc.new { return }
  pr.call

  puts "method end"  
end

def meth3
  puts "method start"

  pr = proc { return }
  pr.call

  puts "method end"  
end

puts "Using lambda"
meth1
puts "--------"
puts "using Proc.new"
meth2
puts "--------"
puts "using proc"
meth3

루비의 폐쇄는 루비에서 블록, 람다 및 proc가 어떻게 작동하는지에 대한 좋은 개요입니다.

람다는 다른 언어와 마찬가지로 예상대로 작동합니다.

Proc.new놀랍고 혼란스럽습니다.

return입니다.Proc.new컨트롤을 자체에서 반환할 만 아니라 컨트롤을 둘러싸는 메서드에서도 반환합니다.

def some_method
  myproc = Proc.new {return "End."}
  myproc.call

  # Any code below will not get executed!
  # ...
end

은 라주장수있다니습할고▁that다라고 주장할 수 .Proc.new블록과 마찬가지로 코드를 포함 메소드에 삽입합니다.그렇지만Proc.new블록이 개체의 일부인 동안 개체를 만듭니다.

그리고 람다와 람다 사이에는 또 다른 차이점이 있습니다.Proc.new이는 그들의 (비공식적인) 인수 처리입니다.람다는 그것에 대해 불평하지만, 반면에Proc.new추가 인수를 무시하거나 인수가 없는 것을 0으로 간주합니다.

irb(main):021:0> l = -> (x) { x.to_s }
=> #<Proc:0x8b63750@(irb):21 (lambda)>
irb(main):022:0> p = Proc.new { |x| x.to_s}
=> #<Proc:0x8b59494@(irb):22>
irb(main):025:0> l.call
ArgumentError: wrong number of arguments (0 for 1)
        from (irb):21:in `block in irb_binding'
        from (irb):25:in `call'
        from (irb):25
        from /usr/bin/irb:11:in `<main>'
irb(main):026:0> p.call
=> ""
irb(main):049:0> l.call 1, 2
ArgumentError: wrong number of arguments (2 for 1)
        from (irb):47:in `block in irb_binding'
        from (irb):49:in `call'
        from (irb):49
        from /usr/bin/irb:11:in `<main>'
irb(main):050:0> p.call 1, 2
=> "1"

그건 그렇고.proc 1, 1+에서는 Ruby 1.8과 같이 합니다. Ruby 1.9+에서는 다음과 같이 동작합니다.Proc.new그것은 정말 혼란스럽습니다.

아코디언 가이의 반응에 대해 자세히 설명합니다.

:Proc.new블록을 통과하여 proc out을 만듭니다.나는 그렇게 믿어요.lambda {...}블록을 통과하는 메서드 호출이 아니라 일종의 리터럴로 구문 분석됩니다. return메서드 호출에 연결된 블록 내부에서 in이 블록이 아닌 메서드에서 반환됩니다.Proc.new케이스는 놀이에서 이것의 한 예입니다.

(1.8입니다.이것이 어떻게 1.9로 번역되는지 모르겠습니다.)

이것에 대해 조금 늦었지만, 훌륭하지만 거의 알려지지 않은 것이 하나 있습니다.Proc.new댓글에 전혀 언급되지 않았습니다.설명서와 같이:

Proc::new블록이 연결된 메서드 내에서만 블록 없이 호출할 수 있으며, 이 경우 해당 블록이 개체로 변환됩니다.

그렇긴 하지만,Proc.new 방법lets to 체인항방법:

def m1
  yield 'Finally!' if block_given?
end

def m2
  m1 &Proc.new
end

m2 { |e| puts e } 
#⇒ Finally!

강조할 가치가 있습니다.returnproc에서 proc는 proc를 호출한 방법이 아니라 proc가 생성된 방법, 즉 proc가 생성된 방법에서 반환됩니다.이것은 프로시저의 폐쇄 속성의 결과입니다.따라서 다음 코드는 아무것도 출력하지 않습니다.

def foo
  proc = Proc.new{return}
  foobar(proc)
  puts 'foo'
end

def foobar(proc)
  proc.call
  puts 'foobar'
end

foo

가 proc 실되경우에서 되지만,foobar은 에생었습다니되성에서 만들어졌습니다.foo 래서그서.return 구출foo,뿐만 아니라.foobarCharles Caldwell이 위에 썼듯이, 그것은 GOTO 느낌이 있습니다. 제생는에각,,return어휘 컨텍스트에서 실행되는 블록에서는 괜찮지만, 다른 컨텍스트에서 실행되는 프로세스에서 사용되는 경우에는 직관성이 훨씬 떨어집니다.

과의 행동의 차이.returnIMHO는 둘 사이의 가장 중요한 차이점입니다. Pronew :-)보다 타이핑이 적기 입니다.

언급URL : https://stackoverflow.com/questions/626/when-to-use-lambda-when-to-use-proc-new

반응형