루비 1.9의 새로운 블럭 문법
December 26th, 2007
루비 1.9.0 - 크리스마스 선물!에서 바뀐 문법 중 가장 눈에 띄는 부분은 바로 블럭과 관련한 부분이다.
block local variables
루비 문법 중 가장 어색한 부분 중 하나가 블럭안에서 정의한 변수의 범위(scope)에 관한 것이었다. 아래 코드를 보자.
- lambda {d = 2; puts d }.call
위 문장을 실행한 후 d를 출력해보면 1.8에서는 2가 출력된다. 블럭이 따로 이름 공간을 갖지 않기 때문이다. 하지만 1.9에서는 NameError가 발생한다. 이제야 블럭 지역 변수가 생긴 것이다.
또 하나, 블럭 인자의 범위도 문제였다.
- a = 1
10.times{|a| puts a}
puts a
믿기 어렵겠지만, 1.8에서 마지막 문장의 결과로 '9'가 출력된다. 블럭 매개 변수마저도 이름 공간이 따로 없었던 것이다.
하지만 1.9에서 같은 예제를 실행해보면 1이 출력됨을 볼 수 있다.
프로그래밍 루비를 번역하면서도 여러번 지적한 적이 있는 루비의 어두운 단면 중 하나인데, 깔끔하게 정리가 되어 다행이다.
lambda != proc
1.8에서 lambda와 proc은 완전히 같다. 하지만 1.9에서는 그 의미가 달라졌다.
결론부터 이야기하면 lambda는 람다, proc은 블록 문법을 따른다. 그리고 그 차이는 매개변수 개수를 검사하는 로직에 있다.
- def test
yield 1
end
test {|a,b|}
위 코드에서는 test 메서드에 블럭을 바인딩하는데 이 블럭이 매개변수를 2개(a,b) 사용한다. 그런데 yield 할 때는 값을 한개만 넘겨준다. 그렇게 하면 자연스럽게 a=1, b=nil이 매핑된다. 이것이 1.8 이후 버전에서 공통적으로 적용되는 블럭 매커니즘이다.
그리고 루비 1.9의 proc은 이 의미를 잘 따른다.
- irb(main):036:0> proc {|a,b| a.to_i+b.to_i}.call(1)
ArgumentError: wrong number of arguments (1 for 2)
1.8에서는 위처럼 매개변수 개수가 잘못되었다는 에러가 발생하지만, 1.9에서는 블럭 문법처럼 잘 동작한다.
- irb(main):003:0> proc {|a,b| a.to_i+b.to_i}.call(1)
=> 1
물론, 1.9에서도 lambda 객체는 ArgumentError를 발생시킨다.
- irb(main):005:0> lambda {|a,b| a.to_i+b.to_i}.call(1)
ArgumentError: wrong number of arguments (1 for 2)
축약 문법
마츠의 발표 중에 재미있는 화면이 있어서 소개한다.
출처: http://www.rubyist.net/~matz/slides/kobe07/index.html
왜 뜬금없이 -> 라는 문법이 추가되었을까 고민 중이었는데, 바로 저런 이유였다. ->이 람다와 비슷하게 생겼다는 것이다. C언어에서는 레퍼런스의 메서드 호출에 사용하는 문법인데, 좀 어색하기는 하지만 저런 설명을 듣고보니 그럴 듯 해 보이기도 한다.
그런 이유로 1.9에서는 이런 축약 표현이 가능해졌다.
- lambda {|a,b| a+b}.call(1,2)
->(a,b){a+b}.(1,2)
위 문장과 아래 문장은 같다. lambda 대신 ->를 쓸 수 있게 되었고 Proc#call을 .으로 줄여쓸 수 있게 되었다. 아직 눈에 익지 않아서 가독성이 좋은지는 잘 모르겠다. IDE가 ->를 람다로 바꿔서 보여주면 좋을 것 같다 :)




December 27th, 2007 at 12:25 AM (myRuby.net) 재충전하면서 재미난 글들 많이 써주시게 ~~ 책 한권 쓸 때도 된 것 같아 ㅎㅎㅎㅎ
December 27th, 2007 at 01:36 AM 잘 쉬고 계세요? ㅋ 회사에 놀러오셔요~~
January 2nd, 2008 at 02:34 PM JasonPA// 책은 무리예요 ^^