Posted by 大山
Sat, 24 Feb 2007 07:20:00 GMT
[참고: 이 글은 함수형 프로그래밍 1 - 함수 합성에 이어지는 시리즈임.]
앞 글에서는 두개 이상의 함수를 합성하여 새로운 함수를 만드는 방법을 살펴보았다. 이번 글에서는 함수에서 일부 인자의 값을 고정하여 새로운 함수를 만드는 커링(Currying) 기법을 다뤄본다. 우선 다음의 함수를 살펴보자.
f(x, y) = x^2 + y^2
g(y) = f(0, y) = y^2
위에서 함수 f는 x, y 두개의 인자를 가지는 함수이다. 함수 g는 함수 f에서 첫번째 인자의 값을 상수로 고정시켜 만든 새로운 함수이다. 이처럼 함수 f에서 일부 인자의 값을 상수로 고정시켜 새로운 함수 g를 만드는 과정을 커링이라고 부른다. (그래프로 보면, z = y^2 그래프의 모습은 z = x^2 + y^2 그래프와 x = 0 그래프가 만나는 단면의 모습이다.)
루비에서 함수 f, g는 다음과 같이 정의할 수 있다.
f = lambda {|x, y| x**2 + y**2}
g = f[0]
하지만 실제로 위의 코드를 실행하면, 두번째 줄에서 함수 f의 인자 개수가 틀리다는 에러가 발생하게 된다. 루비의 함수 호출은 커링 기능을 지원하지 않기 때문이다. 루비에 커링 기능을 추가하기 위해서는 다음의 코드가 필요하다. (이 코드는 Proc 클래스의 [ ] 메소드를 새롭게 정의하고 있다.)
class Proc
def [](*a)
if arity > a.size
lambda {|*b| self[*(a+b)]}
else
self.call(*a)
end
end
end
이제 irb에서 실제로 코드를 입력해보자.
>> class Proc
>> def [](*a)
>> if arity > a.size
>> lambda {|*b| self[*(a+b)]}
>> else
?> self.call(*a)
>> end
>> end
>> end
=> nil
>> f = lambda {|x, y| x**2 + y**2}
=> #<Proc:0x010abc10@(irb#1):10>
>> g = f[0]
=> #<Proc:0x010af310@(irb#1):4>
>> f[0, 5]
=> 25
>> g[5]
=> 25
Posted in 루비 | Tags 루비, 커링, 함수형 프로그래밍 | 6 comments | no trackbacks
Posted by 大山
Sun, 04 Feb 2007 14:20:00 GMT
함수형 프로그래밍이란 함수를 연산의 대상으로 삼는 프로그래밍 패러다임을 말한다. 수학의 함수를 떠올리면 되는데, 우선 다음의 예를 살펴보자.
f(x) = x + 3
g(x) = x^2
h = g * f
위에서 함수 h는 함수 f와 g를 합성한 새로운 함수이다. 이제 함수 h는 다음과 같게 정의된 것이나 마찬가지이다.
h(x) = g(f(x)) = (x + 3)^2 = x^2 + 6x + 9
루비는 객체지향 언어지만, 동시에 함수형 프로그래밍 언어이기도 하다. 이제 루비에서 함수 f와 g를 정의한 후, 이를 합성하여 함수 h를 만드는 과정을 살펴보도록 하자. 루비에서 함수를 정의할때는 lambda란 메소드를 사용한다. (여기에서 말하는 함수란 물론 Proc 객체를 말한다. 일반 메소드와 구분하기 위해 여기에서는 함수라는 표현을 사용하고 있다.)
f = lambda {|x| x + 3}
g = lambda {|x| x ** 2}
이제 함수 f와 g를 결합할 차례인데, 이를 위해서는 다음의 코드를 먼저 선언해 주어야 한다. [1]
class Proc
def *(func)
lambda {|*a| self[func[*a]]}
end
end
위의 코드는 함수 간의 연산인 *를 정의하는데, 이 연산이 바로 함수를 합성하는 연산이다. (위의 코드는 Proc 객체에 * 메소드를 추가하고 있다.) 이제 루비에서 다음과 같은 코드를 작성할 수 있게 된다.
이제 irb에서 실제로 코드를 입력해보자.
>> class Proc
>> def *(func)
>> lambda {|*a| self[func[*a]]}
>> end
>> end
=> nil
>> f = lambda {|x| x + 3}
=> #<Proc:0x0051d3f8@(irb):6>
>> g = lambda {|x| x ** 2}
=> #<Proc:0x0051a978@(irb):7>
>> h = g * f
=> #<Proc:0x0051ff2c@(irb):3>
>> f[2]
=> 5
>> g[5]
=> 25
>> h[2]
=> 25
위에서 'f[2]'는 루비에서 함수를 호출할때 사용하는 방식이다. 이 표현 대신 'f.call(2)'를 사용하는 것 또한 가능하다.
관련글: 함수형 프로그래밍 2 - 커링
Posted in 루비 | Tags 루비, 함수형 프로그래밍 | 12 comments | no trackbacks
Posted by 大山
Mon, 29 Jan 2007 13:04:00 GMT
드디어 프로그래밍 루비가 국내에서 번역되어 출간되었습니다!
프로그래밍 루비의 영문판 출간이 영어권에서 루비가 널리 알려진 계기였듯이, 이번 한글 번역판의 출간이 국내에서 루비가 널리 확산되는 계기가 되리라고 생각합니다. 루비에 관심은 있는데 책이 없어 망설이시던 많은 분들께 희소식이 될 것 같습니다.
제가 집필하고 있는 레일스 책도 곧 마무리지어 선보이도록 하겠습니다. 아마 책이 출간되면, 이 블로그도 다시 활발해질 것 같네요. 글이 뜸하다고 뭐라하시는 분들 조금만 기다려 주세요. ;)
Posted in 루비 | Tags 레일스, 루비 | 9 comments | no trackbacks
Posted by 大山
Sun, 26 Nov 2006 17:42:00 GMT
어제는 첫 루비 세미나 모임이 오픈마루 회의실에서 열렸다. 첫 발표를 맡으신 Ias님은 JRuby에 대한 상세한 내용을 다루어 주셨다. 특히 JRuby의 설정, 사용법, 용도 등과 관련한 내용을 많이 짚어주셔서, JRuby 사용을 염두에 두고 있는 분들에게 많은 도움이 되었을듯.
두번째 발표는 정목님의 Capistrano 발표였는데, 깔끔한 프레젼테이션 스킬이 돋보이는 발표였다. Capistrano는 레일스 Deployment를 자동화시켜주는 툴인데, 덕분에 Capistrano를 사용하는 과정 전체를 잘 들여다 볼 수 있었다.
세번째 발표는 내가 준비한 루비 메타 프로그래밍이었다. 메타 프로그래밍은 루비에서 런타임에 동적으로 메소드를 추가하는 프로그래밍 기법으로, 레일스 등에서 널리 응용되고 있는 기능이다.
예를 들어, 다음처럼 Base 클래스에 'my_attr_accessor'이란 클래스 메소드가 정의되어 있다고 가정해보자.
class Base
def self.my_attr_accessor(str)
class_eval "def #{str}; @#{str}; end"
class_eval "def #{str}=(value); @#{str}=value; end"
end
end
위에서 'my_attr_accessor' 클래스 메소드는 'class_eval' 메소드를 호출하여 문자열로 작성된 루비 코드를 실행시킴을 알 수 있다. 이 때문에 Base 클래스를 상속받는 모든 클래스는 단지 'my_attr_accessor' 메소드를 호출함으로써 특정 인스턴스 변수에 대한 접근자 메소드를 동적으로 정의할 수 있다. 즉, 다음 두개의 Person 클래스 정의는 논리적으로 동일하다.
class Person < Base
my_attr_accessor "name"
end
class Person
def name
@name
end
def name=(value)
@name=value
end
end
실제로 루비에는 'my_attr_accessor'와 비슷한 기능을 하는 'attr_accessor'라는 메소드가 이미 정의되어 있어 새로운 클래스를 정의할때 사용할 수 있다.
막상 발표를 끝내고 보니 구체적인 예를 더 준비하지 못한게 아쉬웠는데, 마침 deepblue님의 루비를 즐겨요 발표가 내용적으로 이어지는 발표가 되어 좋았다. 이 발표는 과연 '루비스러운 코드는 무엇인가'에 관한 내용이었는데, 다소 형이상적일수도 있는 이 물음에 deepblue님은 다음과 같은 답을 제시했다.
루비스러운 코드는 개발자가 고민한 시간이 묻어있는 사람 냄새나는 코드입니다.
위의 구절에서도 deepblue님의 고민과 사람 냄새가 느껴지는 듯. :)
다섯번째 발표는 seradin님의 Groovy/Grails에 관한 내용이었다. seradin님의 세련된 말솜씨가 돋보이는 발표였는데, 덕분에 Groovy/Grails에 대한 내용을 쉽게 파악할 수 있어 좋았다. Groovy는 자바의 스크립팅 언어 지원 정책과 관련해서도 유심히 지켜봐야할 언어일듯 싶다.
아쉽게도 저녁에 다른 약속이 잡혀있어 끝까지 참석하지는 못했지만, 다른 분들의 후기와 발표자료를 읽어보니 모두 유익하고 흥미로운 발표였던 것 같다.
다소 아쉬웠던 점은 아무래도 발표가 중심이다보니 토론이 쉽게 이루어지지는 않는 면이 있었다. 다음부터는 세미나 주제를 두어개로 고정해서, 조금 더 토론 중심적인 모임을 가져보면 어떨까하는 생각도 든다.
Posted in 루비 | Tags 루비, 메타프로그래밍, Capistrano, JRuby | 11 comments | no trackbacks
Posted by 大山
Fri, 27 Oct 2006 19:42:00 GMT
지난 며칠간 루비 컨퍼런스 참석차 미국 덴버에 다녀왔다. 덴버는 나중에 여행만을 위해 다시 찾고 싶을 만큼 무척 아름다운 도시였다는 생각.
다른 컨퍼런스에서는 보통 세션 3-4개가 동시에 진행되기 마련인데, 루비 컨퍼런스는 단일 트랙으로 구성되어 있었다. 참석자 모두가 동일한 경험을 공유하기 위해서라는데, 그것보다도 쉬는 시간에 여유롭게 사람들과 이야기를 나눌 수 있어 좋았다. 컨퍼런스룸이 가로로 길고 좌우 양쪽으로 프로젝터가 설치되어 있어서 그런지, 300명이 넘는 참석자에도 불구하고 비교적 아담한 느낌.
첫날은 타카하시상의 "루비의 역사" 발표와 Evan Phoenix의 Rubinius 발표를 재미있게 들었다. 가장 흥미로웠던 내용은 일본 개발자들이 영어를 잘 못해서 파이썬보다 루비에 관심을 가지게 되었고, 덕분에 루비가 발전할 수 있었다는 점. 이런 경우엔 영어를 못하는 것이 유리할수도 있겠다는 생각이 들었다. Rubinius는 뒤에서 설명.
두번째 날에는 흥미로운 발표가 많았는데, 개인적으로 가장 좋았던 발표는 Nathaniel Talbott의 "Open Classes, Open Companies"였다. Nathaniel은 루비 컨퍼런스 2005의 "Rails: Serving the long tail in 1883 and 2005", 레일스 컨퍼런스 2006의 "Homesteading: A Thriver's Guide"에 이어 역시나 많은 영감을 주는 이야기를 들려주었다. 대략적인 내용은 루비의 동적 특성, 간결성, reflection, 개방성 등을 사업에 그래도 적용하자는 것. 상당히 공감이 가는 내용이었는데, 재미있는 것은 발표 후에 누군가가 그런 형태의 사업은 확장성(Scalability)에 문제가 있지 않겠냐는 질문을 했다는 점이다. 루비를 처음 접하는 사람 중에도 종종 확장성은 어떠냐며 괜한 걱정을 하는 경우가 있지 않은가. 경쟁력있는 사업을 만드는 것이 우선이지 단지 사람수를 늘리는 것이 중요한 것은 아닐텐데 말이다.
또다른 재미있는 발표로는 애플의 개발자인 Laurent Sansonetti의 "Leveraging Mac OS X from Ruby"를 꼽을 수 있다. 이 발표는 Laurent가 개발하고 있는 RubyOSA와 RubyCocoa에 관한 내용이었다. RubyOSA는 기존의 AppleScript를 루비로 대체하는 라이브러리로, 맥 OS X의 GUI 애플리케이션을 루비로 스크립팅할 수 있게 해준다. 예를 들면, 포토샵을 시작하여 어떤 폴더에 있는 이미지를 모두 열고, 이를 특정 사이즈로 리사이징 하는 작업을 모두 루비로 자동화할 수 있다. Laurent는 irb에서 루비 코드만을 사용하여 iTunes를 시작하고, 특정 노래를 플레이하고, 볼륨을 조정하는 데모를 보여주었다. 모두들 환호했던 것은 물론이다. 개인적으로 AppleScript의 신택스에 불만이 많았기에 무척 반가운 소식이었다. 혹시 RubyOSA를 설치하실 분은, 먼저 루비를 1.8.5로 업그레이드 하도록. RubyCocoa는 뒤에서 설명.
가장 논란이 된 발표는 XML의 공동 창시자인 Tim Bray의 "I18n, M17n, Unicode, and all that" 발표였던듯 싶다. 결론만 요약하면, 자신은 썬마이크로시스템즈에서 근무하지만, 최근에 루비 팬이 되었다. 루비의 유니코드 지원은 아직 완전하지 못하다. 어떻게든 루비에서 유니코드 지원이 빨리 이루어졌으면 좋겠다 정도였던 것 같다. Tim의 의도는 아니었겠지만, 그의 발표는 유니코드의 취약점을 잘 드러내기도 했다. Tim은 유니코드 문자열에서, capitalize, upcase, downcase 등의 메소드를 지원하는 것은 위험하다고 주장했다. 영어 알파벳만 놓고 보면 모르지만, 전세계 charset이 모두 포함된 유니코드에서는 대소문자의 구별이 규칙적이지 못하기 때문이라는 것이다. 유니코드는 이처럼 모든 charset을 동시에 다룰 수 있는 장점이 있는 반면, 개별 charset에만 적용되는 메소드는 지원하기가 어중간하다는 단점이 있다. 나는 이런 이유 때문에라도 루비 2.0에서처럼 문자열마다 인코딩을 별도로 지정하는 방식이 모두에게 유니코드를 강요하는 방식보다 더 유연할 것이라고 지적했는데, Tim은 그다지 수긍하고 싶어하지 않는듯. 아무튼 Tim의 발표로 인해 컨퍼런스 내내, capitalize는 위험한 메소드라는 농담이 끊이질 않았다.
둘째날 저녁식사 후에는 Matz의 기조연설이 있었다. Matz는 루비 1.9.1이 2007년 크리스마스에 릴리즈될 것이라고 선언을 했다. 기조연설의 주요 내용은 커뮤니티가 루비 2.0의 설계에 보다 활발하게 참여할 것을 요청하는 것이었다. 각종 제안을 수렴하고 논의하기 위한 별도의 웹 사이트가 곧 만들어질 예정이라고 한다. 새로운 웹 사이트가 만들어지면, 개인적으로도 열심히 참여해야겠다는 생각.
마지막 날에는 코이치상의 Yarv 발표, 그리고 John Lam의 RubyCLR 발표를 관심을 가지고 들었다. 이제 Yarv는 왠만한 루비 프로그램은 다 잘 실행하는 단계가 되었다고 한다. 코이치상은 Yarv에서 레일스가 실행되는 것을 시연하였고, 모듈에 따라 Yarv의 실행속도가 최고 20배까지나 빨라졌다는 벤치마크를 공개하였다.
한가지 흥미로운 점은 루비의 실행환경이 부지기수로 늘어나고 있다는 것. 공식 루비 실행환경인 루비 1.8과 Yarv 이외에도 JRuby, RubyCLR, Ruby.NET, RubyCocoa, Rubinius 등이 모두 현재 활발하게 개발되고 있는 루비의 실행환경이다. JRuby는 자바로 구현된 루비 실행환경으로 루비에서 자바 클래스를 사용할 수 있도록 해준다. 일종의 루비/자바 브릿지 역할을 한다고도 볼 수 있는데, JRuby의 메인 개발자인 Charles Nutter는 곧 JRuby가 루비 코드를 자바 바이코드로 컴파일하는 기능도 갖추게 될 것이라고 했다. JRuby 프로젝트는 최근에 썬마이크로시스템즈에 인수되기도 했는데, 썬도 자바의 언어적 한계를 인정하고 점차 JVM을 범용 가상머신으로 재포지셔닝하고 있다는 느낌이다.
RubyCLR은 일종의 루비/.NET CLR 브릿지로 루비에서 C# 클래스를 접근할 수 있도록 해준다. RubyCLR을 사용하면, 루비로 윈도우 GUI 프로그래밍을 할 수 있다는 얘기. 컨퍼런스 중에 RubyCLR 프로젝트 역시 마이크로소프트에서 인수한다는 발표가 있었다. 마이크로소프트가 썬의 JRuby 인수에 자극을 받은건 아닐지. :) Ruby.NET은 RubyCLR보다 한걸음 더 나아가 루비 코드를 CLR 바이트코드로 컴파일해주는 독자적인 루비실행환경이다. 마이크로소프트가 Ruby.NET 대신 RubyCLR을 인수한 것은 다소 의문이지만, nohmad님이 답글에서 지적하신대로 Ruby.NET이 대학교 연구실에서 진행하는 프로젝트라 그럴수도 있겠다는 생각이 든다.
RubyCocoa는 루비로 맥 OS X의 Cocoa 클래스를 사용할 수 있게 해주는 루비/Objective-C 브릿지 라이브러리이다. JRuby나 Ruby.NET처럼 독자적인 루비 실행환경은 아니지만, 기존 루비의 실행환경에서 맥 OS X GUI 프로그래밍을 가능하게 해준다는 면에서 개인적으로는 더 선호하는 방식이다. Laurent에 따르면, 애플은 맥 OS 10.5 Leopard를 RubyCocoa와 RubyOSA를 포함한 통합 루비 프레임워크를 번들하여 출시할 예정이라고 한다.
Rubinius는 일종의 대안 루비 실행환경이라고 볼 수 있는데, 코드베이스를 보다 간소화하고, C 코드를 직접 작성하는 대신 루비로 루비 가상머신을 구현한 다음, 루비 코드를 C 코드로 변환하는 방식을 사용하여 개발하고 있다고 한다. 마지막으로 구글 Summer of Code 프로젝트 중에는 핸드폰(Symbian OS)에 루비를 컴파일하는 Ruby-Symbian 프로젝트도 있었다고 한다. 자바, 윈도우, 맥 OS X, 그리고 핸드폰에서 모두 루비를 지원하다니, 상당히 고무적이라는 생각. :)
추가적으로 궁금한 사항은, 답글로 질문주시길.
업데이트: nohmad님이 답글에서 지적하신대로 RubyCLR은 루비 런타임 환경이 아니라, Ruby/.NET CLR 브릿지 라이브러리였습니다. 본문 내용을 이에 맞게 수정합니다.
Posted in 루비 | Tags 루비, rubyconf | 15 comments | no trackbacks
Posted by 大山
Sat, 07 Oct 2006 13:39:00 GMT
루비 한국어 홈페이지가 드디어 오픈했습니다! 번역에 수고하신 deepblue님께 박수~ :)
Posted in 루비 | Tags 루비 | 2 comments | no trackbacks
Posted by 大山
Thu, 28 Sep 2006 07:14:00 GMT
마이크로 소프트웨어 10월호에서 루비가 스페셜 리포트로 다뤄졌습니다.
1부는 제가 기고를 했기에 마소의 허락 하에 링크를 겁니다. 링크에서는 원래 제가 붙였던 제목인 "생각의 폭을 넓혀주는 프로그래밍 언어, 루비"를 사용하고 있습니다.
업데이트: 송치형님의 SR 3부 "레일스의 꽃, 액티브 레코드 집중 분석"도 링크합니다.
업데이트 2: 김석준님의 SR 2부 "루비 온 레일스로 만나는 차세대 웹!"도 링크합니다.
Posted in 루비 | Tags 루비, 마소 | 8 comments | no trackbacks
Posted by 大山
Sun, 06 Aug 2006 17:51:00 GMT
[참고: 이 글은 루비가 쿨한 이유 1 - irb, 루비가 쿨한 이유 2 - 블록에 이어지는 시리즈임.]
해시(Hash)는 Associative Array라고도 종종 불리는데 루비에서 가장 많이 쓰이는 데이타 구조 중 하나이다. 해시에는 키값과 데이타가 짝으로 저장되는데, 다음과 같은 식이다.
h = Hash.new
h["name"] = "홍길동"
h["age"] = 18
h["sex"] = "남자"
저장한 데이타를 불러오려면 원래의 키값만 알고 있으면 된다. 예를 들어, h["name"]은 "홍길동"을 리턴한다. h["address"]와 같이, 존재하지 않는 키값이 입력되면 nil이 리턴된다.
해시는 대부분의 프로그래밍 언어에서 지원되지만, 모든 프로그래밍 언어에서 같은 빈도로 활용되지는 않는다. 보통 Perl이나 루비 코드에는 해시가 넘쳐나는데 반해, 자바 코드에서는 해시를 찾아보기가 어렵다.
이런 현상은 프로그래밍 언어는 평등하지 않다는 것을 보여주는 또다른 예라고 할 수 있다. 자바의 해시는 HashMap 클래스의 API를 통해서만 사용이 가능하지만, 루비나 Perl은 언어의 신택스 레벨에서 해시를 지원하기 때문이다.
예를 들어, 자바에서 숫자와 요일을 매핑하는 해시를 만드려면 다음과 같은 코드가 필요하다.
import java.util.HashMap;
class HashExample {
static void main(String[] argv) {
HashMap h = new HashMap();
h.add(new Integer(0), "일요일");
h.add(new Integer(1), "월요일");
h.add(new Integer(2), "화요일");
h.add(new Integer(3), "수요일");
h.add(new Integer(4), "목요일");
h.add(new Integer(5), "금요일");
h.add(new Integer(6), "토요일");
}
}
루비에서는 다음과 같다.
h = {0 => "일요일", 1 => "월요일", 2 => "화요일",
3 => "수요일", 4 => "목요일", 5 => "금요일",
6 => "토요일"}
왜 자바 개발자들이 해시를 잘 안쓰는지는 읽는 분의 상상에 맡긴다. 해시가 유용한 경우는 정말로 많은데, 대표적인 예는 특정 이벤트가 일어난 횟수를 저장하기 위해서이다. 예를 들어, 웹 로그 파일에서 특정 IP 주소의 접속 빈도를 합산하는데 사용할 수 있다.
c:\> irb --simple-prompt
>> f = File.open("access_log", "r")
>> h = Hash.new(0)
>> f.each {|line| h[$1] += 1 if line =~ /^(\d+\.\d+\.\d+\.\d+)/}
위에서 Hash.new(0)이라고 한 것은, 해시에 아직 저장되지 않은 키값을 입력했을때 nil 대신에 0을 리턴하도록 해준다.
해시의 키값이나 데이타에는 어떤 객체도 들어갈 수 있기 때문에 또다른 해시 객체가 데이타로 들어갈 수도 있다. 예를 들어 다음과 같은 식이다.
h = {1 => {"name" => "이승만", "from" => 1948, "to" => 1960},
2 => {"name" => "윤보선", "from" => 1960, "to" => 1962},
3 => {"name" => "박정희", "from" => 1963, "to" => 1979},
4 => {"name" => "최규하", "from" => 1979, "to" => 1980},
5 => {"name" => "전두환", "from" => 1980, "to" => 1988},
6 => {"name" => "노태우", "from" => 1988, "to" => 1993},
7 => {"name" => "김영삼", "from" => 1993, "to" => 1998},
8 => {"name" => "김대중", "from" => 1998, "to" => 2003},
9 => {"name" => "노무현", "from" => 2003, "to" => 2008}}
대통령들의 재임 기간을 계산해 보는 것도 간단하다.
(1..9).each do |i|
puts h[i]["name"] + ": " +
(h[i]["to"] - h[i]["from"]).to_s + "년"
end
이승만: 12년
윤보선: 2년
박정희: 16년
최규하: 1년
전두환: 8년
노태우: 5년
김영삼: 5년
김대중: 5년
노무현: 5년
루비 설치는 이곳을 참고!
Posted in 루비 | Tags 루비, 해시 | 6 comments | no trackbacks
Posted by 大山
Thu, 03 Aug 2006 08:36:00 GMT
오늘 아침에 루비 컨퍼런스 2006의 등록이 시작되었다는 rss feed를 확인하자마자 서둘렀는데도 등록을 못했다. 250석이 4시간만에 동났다고 한다. 레일스 컨퍼런스 2006의 등록이 1주일만에 마감된 것에 이어 새로운 신기록일듯.
업데이트: 대기자 명단에 올라 있다가 5일만에 등록 성공. :)
Posted in 루비 | Tags 루비, rubyconf | no comments | no trackbacks
Posted by 大山
Tue, 25 Jul 2006 02:20:00 GMT
[참고: 이 글은 루비가 쿨한 이유 1 - irb에 이어지는 시리즈임.]
블록을 처음 접한 사람은 조금 당황하게 마련이다. 자바나 C 등의 기존 언어에서는 전혀 볼 수 없었던 기능이기 때문이다. 조금 새롭겠지만 정말로 강력하고 편리한 기능이므로 심호흡을 가다듬고 꼭 읽어보시길.
프로그래밍을 하다보면 배열의 내용물을 차례차례 하나씩 처리해야 하는 경우가 늘상 있다. 이런 경우에 자바와 같은 언어에서는 다음처럼 for 루프를 쓰는게 보통이다.
import java.util.*;
class PrintArray {
public static void main(String[] argv) {
String[] arr = {"mike", "nancy", "john", "cathy"};
for (int i=0; i<arr.length; i++) {
System.out.println(arr[i].toUpperCase());
}
}
}
인덱스 변수를 따로 선언해서 써야 하는게 엘러건트하지 않기 때문에, 이터레이터(Iterator)를 쓰기도 한다.
import java.util.*;
class PrintArray {
public static void main(String[] argv) {
Iterator it = Arrays.asList({"mike", "nancy", "john", "cathy"}).iterator();
while (it.hasNext()) {
System.out.println(it.next().toUpperCase());
}
}
}
루비에서는 이렇게 한다.
["mike", "nancy", "john", "cathy"].each {|name| puts name.upcase}
여기서 { |name| puts name.upcase } 부분이 바로 블록이다. 배열의 each라는 메소드에 이 코드를 넘겨주면, each가 배열의 내용물을 차례차례 하나씩 거쳐가면서, 블록을 호출하게 된다. 즉 루비에서는 변수만 인자로 넘겨주는 것이 아니라, 실행할 수 있는 프로그램 코드를 인자로 넘겨주는 것도 가능한 것이다.
블록은 C의 함수 포인터와도 비슷한데 정확히는 클로저라는 개념이다. 이전까지는 Lisp이나 Smalltalk에서 주로 쓰이던 기능이라는 정도만 알아 두자. 그럼 블록을 사용하는 예를 몇 개 더 보도록 하자.
배열의 내용물을 하나씩 처리(문자열을 대문자로 변환)해서, 새로운 배열을 만드는 경우:
c:\> irb --simple-prompt
>> ["mike", "nancy", "john", "cathy"].map {|name| name.upcase}
=> ["MIKE", "NANCY", "JOHN", "CATHY"]
배열의 내용물 중에서 특정 조건(문자열에 "y"가 포함된 경우)을 만족시키는 내용물만 추려내는 경우:
>> ["mike", "nancy", "john", "cathy"].find_all {|name| name.include?("y")}
=> ["nancy", "cathy"]
배열의 내용물 전체가 특정 조건(짝수)을 만족시키는지 테스트하는 경우:
>> [2, 10, 8, 26, 32].all? {|num| num%2 == 0}
=> true
정말 엘러건트하지 않은가. 여기서 다룬 것은 블록의 가장 초보적인 예일 뿐이다. map, find_all, all? 같은 메소드는 모두 루비의 일반 메소드이다. 루비 프로그래머는 얼마든지 블록을 인자로 받는 새로운 메소드를 정의해서 사용할 수 있다.
이제 망설이지 말고 어서 루비를 설치해서 사용해 보자.
관련글: 루비가 쿨한 이유 3 - 해시
Posted in 루비 | Tags 루비, 블록 | no comments | no trackbacks