2013년 12월 12일 목요일

[ROR] Proc.new, block, lambda에 관해서..

안녕하세요 belhyun입니다.
rails 공부를 하면서 이해하기 어려웠던 점이 Proc.new, Block, lambda에 관한 것이였습니다.
그래서 이 부분을 정리해보려고 이렇게 글을 쓰게 되었습니다.
먼저 이 세가지의 개념은 작은 코드조각이라고 생각할 수 있습니다.
예제를 확인한 후 구체적으로 알아보도록 하겠습니다.

#Block Examples
[1,2,3].each { |x| puts x*2 } #블락은 {}으로 묶입니다.

[1,2,3].each do |x|
  puts x*2
end

#Proc Examples
p = Proc.new { |x| puts x*2 }
[1,2,3].each(&p) #&기호는 proc을 block으로 바꾸라는 의미입니다.

p = Proc.new { puts "Hello World" }
p.call #proc 객체의 몸체가 호출될 때 실행됩니다. 

#Lambda Examples
lam = lambda { |x| puts x*2}
[1,2.3].each(&lam)

lam = lambda{ puts "Hello World"}
lam.call #역시 lambda의 몸체가 호출될 때 실행됩니다. 

위에서 보시는 것과 같이 이 세가지의 개념은 비슷하게 쓰입니다. 차이점을 알아보도록 하겠습니다.

Block과 Procs의 차이점

1. Procs은 객체이고, blocks의 객체가 아닙니다. 
p 객체는 Proc 클래스의 인스턴스입니다.
p = Proc.new { puts "Hello World" }
그리고 이 사실은 객체의 메소드를 호출할 수 있고, 변수에 객체를 할당할 수 있다는 것을 알려줍니다. Procs는 또한 자기자신을 리턴할 수도 있습니다. 다음은 그 예제입니다.
p.call #prints 'Hello World'
p.class #return 'Proc'
a = p 
p
대조적으로, block은 메소드 호출을 위한 문법중의 하나일 뿐입니다. block은 단독의 의미가 아닙니다. 인자 리스트의 하나로도 사용될 수 있습니다. 다음은 그 예제입니다.
{puts "Hello World"} #문법에러가 발생합니다. 단독으로 block은 쓰일 수 없기 때문입니다.
a = {puts "Hello World"} #마찬가지의 이유로 문법에러가 발생합니다.
[1,2,3].each{ |x| puts x*2} # 메소드 호출을 위한 문법의 한 부분으로 쓰입니다.

Proc과 Lambda의 차이점

1. Proc과 Lambda는 'return'키워드를 다루는데 있어 차이점이 있습니다.
다음의 코드를 확인해 보도록 하겠습니다.

def lambda_test
  lam = lambda { return }
  lam.call
  puts "Hello world"
end

lambda_test                 # calling lambda_test prints 'Hello World'
위에서 보시는 것처럼, { return }은 lambda의 바로 바깥쪽에 있는 코드를 실행시킵니다.
def proc_test
  proc = Proc.new { return }
  proc.call
  puts "Hello world"
end

proc_test                 # calling proc_test prints nothing
반면 Proc은 아무것도 호출하지 않습니다. 왜냐하면 Proc은 Lambda와 달리 Proc이 실제로 호출되는 시점의 바로 다음의 코드를 실행시키기 때문입니다.

댓글 없음:

댓글 쓰기