Ruby for Impatient Nuby #2

Tags:

본 글은 http://docs.google.com/View?docid=ajb44wcvmjj8_2fg33f2로 이전되었습니다.

Comments

16 responses to “Ruby for Impatient Nuby #2”

  1. 번에 나누어서 연재하려고 합니다. 특정 주제에 대한 요청이 있으면 반영을 할 예정이니 피드백 바랍니다. 이번 작업은 서민구님의 제안으로 시작되었으며, 민구님의 루비 튜토리얼 파트 1과 파트 2를 같이 참고하면 레일스를 익히는데 많은 도움이 될 것입니다.] 레일스는 루비로 만들어진 웹개발 프레임워크이다. 루비만의 강력함과 몇 가지 획기적인 아이디어로 인해 레일스에서의 웹

  2. 공성식 Avatar
    공성식

    중요한 개념들이 많이 언급됐네요.
    감사하구요, 그냥 몇 가지 사소한 제 의견만 제시하겠습니다.

    [1]
    ———-
    1) 블록, 2) Proc/proc, 3) labmda
    ———-

    위의 분류는 좀 잘못된 것 같습니다.
    다음과 같이 하는 게 나을 것 같아요.

    ———-
    1) 블록, 2) Proc.new, 3) labmda/proc
    ———-

    proc은 사실상 lambda의 alias죠. lambda/proc은 말씀하신 것처럼 Proc.new와는 약간 다릅니다. 언급하신 인자의 갯수를 체크하는 것과 함께 return을 처리하는 방식이 다릅니다. 대부분의 경우 Proc.new보다는 lambda가 더 유용하죠. proc은 조만간 없어질 계획이므로 가급적 사용하지 않는 게 좋겠구요.

    [2]

    ————
    def f(a, &blk)
    yield a + 1
    end
    ————

    위의 예제는 틀린 경우는 아니지만 약간 awkward한 경우입니다.
    yield를 사용할 경우엔 implicit 블록을 지칭하고 명시적으로 블록을 Proc object로 바꿨을 경우엔,
    blk.call a + 1 과 같이 하는 게 더욱 루비스러울 것 같습니다.
    그렇지 않다면 굳이 blk라는 이름을 주는 의미가 없을 테니까요.
    그러므로 다음과 같은 두 가지 경우 중 하나가 더 좋겠네요.

    def f a
    yield a + 1
    end

    def f a, &blk
    blk.call a + 1
    end

    [3]
    ————
    바로 closure라는 것입니다. 가슴에 손을 얹고 생각해봅시다. 과연 지금 당신이 가장 잘하는 언어중 그 어떤 것이 이정도까지의 자유를 부여하나요?
    ————

    물론 저도 루비의 신택스를 가장 좋아합니다만, JavaScript도 사실 무척 강력한 언어입니다.

    function generate_stack() {
    var stack = new Array();
    var push = function(n) {
    stack.push(n);
    }
    var pop = function() {
    return stack.pop();
    }
    return [push, pop];
    }

    거의 루비 신택스와 비슷하게 closure의 구현이 가능하죠?

    훌륭한 루비 설명서가 만들어지길 기대합니다.

  3. MKSeo Avatar
    MKSeo

    감사합니다… 사소한게 아니라 제가 모르는게 너무 많아 잘못썼네요;;;; 수정해보도록 하겠습니다.

    흠.. 그리고 저런 말은 뺄까요? ㅎㅎ 사실 C++, C, JAVA, C# 등의 언어를 겨냥한 말이었는데. 실은 몇가지는 자바나 C++의 구현과 비교하고 싶지만 최대한 글을 짧게하고 싶어서 참고 있어요… 자바스크립트도 멋지군요 ㅎㅎ

  4. 공성식 Avatar
    공성식

    전체적으로 아주 훌륭하니까 제 말에 신경쓰지 마시고 계속 해나가시길 바랍니다.
    어차피 제가 작성해도 몇 가지는 실수가 있을 테니까요.
    원래 흠잡는 건 쉽잖아요.
    작품을 만드는 건 어렵구요.

  5. MKSeo Avatar
    MKSeo

    도와주셔서 감사합니다. ㅎㅎ
    암도 반응이 없으면 오히려 힘빠질거예요.

  6. 아즈 Avatar

    형 이런걸 원했어요~ ㅋ

  7. MKSeo Avatar
    MKSeo

    재밌게 보길. 다쓰면 ruby-doc.org 에 공식 한국 문서로 등록해달라고 요청할거삼 ㅎㅎ

  8. 공성식 Avatar
    공성식

    민구님, 수고 많으시네요.

    [1]

    이번 글에서 아주 중요한 오류가 있습니다.

    끝에서 두번째 예제에서요…

    def foo
    puts “foo”
    end

    이건 public이 아닙니다.
    Top-level에 정의된 메소드는 Kernel의 private method가 됩니다.
    (Kernel은 Object에 mixin되기 때문에 결국엔 Object의 인스턴스 메소드가 되구요.)
    private이기 때문에 self 이외의 receiver를 통해서는 호출할 수 없습니다.
    그런데 예제에서 o.foo 가 제대로 실행된 것은 irb에서 하셨기 때문입니다.
    ruby 로 직접 돌리시면 에러가 발생할 거예요.
    Kernel.private_methods.grep “foo” 를 해보시면 확인해 보실 수 있습니다.
    (irb에서 말구, 진짜 루비에서요)

    default access modifier가 public인 것은 맞지만 top-level에서는 예외죠.
    top-level은 main이라는 특별한 object 내의 scope이 적용되는 매우 특이한 경우입니다.
    irb는 엄밀히 말하면 ruby가 아니고, 그냥 비슷하게 emulate만 합니다.
    실제로도 별개의 interpreter를 사용합니다.

    [2]

    access modifier에 대한 설명도 약간 헷갈릴 수가 있을 것 같습니다.
    public은 그냥 아시는 대로 다른 언어와 동일하게 이해하시면 될 것 같구요.
    private과 protected은 다른 언어(C++, C#…)의 protected와 비슷합니다.
    동일한 클래스 또는 그 클래스로부터 상속받은 클래스에서 접근할 수 있죠.
    다만 다른 점은 private은 self로만 접근이 가능하고(self는 default receiver이므로 없어도 되죠),
    protected는 self 이외의 receiver로도 접근이 가능합니다.

    가장 많이 사용되는 예는, 메소드가 인자로 동일한 클래스의 인스턴스를 받아 자신(self)과 비교할 때입니다.
    이때는 인자로 넘어온 오브젝트의 메소드에 접근해야 하기 때문에 동일한 클래스라 할지라도 private일 경우엔 접근이 안 됩니다.
    보통 다른 언어에서는 private은 자신의 클래스에서만 접근이 가능하고 상속받은 클래스에서는 접근이 안 되는데 루비에서는 의미가 달라 주의해야 합니다.

    문서의 완성도가 점점 높아지고 있네요…:-)
    계속해서 건필하시길…

  9. MKSeo Avatar
    MKSeo

    (1) Right. ‘foo’ should be described as private!!! I made a serioud mistake. The point I was trying to say is that puts is a private method. So it can’t be called from the outer; e.g., Object.new.puts raises an error.

    But, at some point, I’ve just messed everything up and talked about public. (don’t know why T_T)

    (2) I had to explain public/protected/private in more detail as you’ve shown above. I’ll copy and paste yours. :-)

    Sorry for english, but my Korean input util in Ubuntu sucks! (it drives me crazy sometimes.)

  10. abraxsus Avatar

    ^^; 친구야. 미안.
    전체적으로 1부에서 너무 난이도가 뛰는 경향이 있당..흐이~
    내용이 너무 많아서 1.5부정도가 중간에 있어줘야 좋을것 같은데..
    너무 그러면 본격적인 입문서가 되려나??
    생초보인 나로서는 난이도도 난이도지만 중간중간에 생략되는 정보들이 너무 많다..
    내가 aggressive한건지는 몰라도 자꾸만 질문들이 fork되는구나..ㅎㅎ
    물론 이 코멘트들을 무시해도 좋다. ㅎㅎ.. 다 받아주다보면 진짜 본격적인 입문서가 된다구..
    나는 아무래도 impatient는 아니구 aggressive인가보다..ㅋㅋ..
    내가 좀더 많이 알게되면 공동저자어때? ㅋ..

    1) yield에 대해서 좀더 설명이…
    코드에 yield가 여러번 나와도 일단 yield가 나왔다면 블록이 인자로 필요한거냐?
    블록 여러개를 넘길땐?

    2) 아..&blk이 먼저나오고 이걸 yield라는걸로 대체할수 있다..라고하는게 흐름이 좋을듯한데..

    3)
    irb(main):315:0> def f(a)
    irb(main):316:1> yield a+1
    irb(main):317:1> end
    => nil
    irb(main):318:0> f(1) {|n| puts n}
    2
    => nil
    irb(main):319:0> f 1, {|n| puts n}
    SyntaxError: compile error

    왜 이건 안되지.. 괄호없어도 call된다며..ㅠㅠ

    irb(main):320:0> l
    => [1, 2, “str”, 4]
    irb(main):321:0> l[2]
    => “str”
    irb(main):322:0> l[2] = {|n| puts n}
    SyntaxError: compile error

    음.. 코드 대입은 안되넹-_-;

    4) 스택코드에서 갑자기 s1_push, s1_pop = generate_stack
    => [#, #]

    이거 코드 주소같은데 그럼 s1_push와 s1_pop은 1부에서 나오지 않은 타입인것같은데..
    기본 타입에 이것도 추가되어야하는거 아닌가.

    7)
    $가 붙은 변수는 모지? 이름의 일부일뿐인건가 아님 특별한 의미가 있어?

    8)
    class 는 항상 new라는걸로 생성?

  11. abraxsus Avatar

    나도 다른 언어좀 해볼라는데, 루비 괜찮은 선택이냐?
    루비나 펄, 뭐 이런애들 있자나..
    내가 원하는건
    simple하면서 elegant하면서 최고의 productivity를 자랑하는.. 뭐 그런 언어..
    너의 생각을 듣고싶다.. 뭘 추천할래..
    근데 루비 참 예쁜거 같다. elegant한걸.. 난 괜찮은 선택같은데..ㅎㅎ.

  12. MKSeo Avatar
    MKSeo

    내 생각엔 이래.

    소프트웨어 개발자가 되려면, 랭귀지의 측면에선
    C/C++은 기본적으로 잘해야함. (이런말 하는 내가 부끄럽지만;)
    리눅스 기본적으로 잘해야함.
    SQL은 뭐든지 다 짤 수 있어야함.
    어셈블리는 해도 그만 안해도 그만이지만 하면 좋겠다.
    웹 프로그래밍은 php는 알아야하고, 그 외 한가지 더 알면 좋겠다.
    그리고 마지막으로 그 glue language 라고 해야하나..
    스크립트를 하나 알아야하는데, 내생각에 루비하는건 너무 리스크가 크다.

    파이썬 해.
    나도 파이썬으로 옮겨가기로 결심.
    파이썬 솔직히 elegant하지 않다. 왕무식. (물론 C보다 유식;;; 말장난 미안;;)
    그러나 그 만의 단순함도 있는 듯.

    빠르게 코딩하고 실행시 퍼포먼스 받쳐주고 코드 보여줬을때 문외한도 대강
    이해하며 넘어갈 수 있는 언어는 이거 밖에 없는 것 같다.

  13. 골빈해커 Avatar

    저는 소프트웨어 개발자가 되긴 글렀군요..제대로 하는게 없네;; OTL

    암튼 결론은 젤 좋은건 펄(…)

  14. MKSeo Avatar
    MKSeo

    골빈씨는 ‘해커’죠. ㅎㅎ
    펄 모르는 해커는 명함 내미기 힘든거 같아요.
    저번에 DRM 깼던 코드도 아마 펄이었죠? ㅋㅋ
    그것도 왕무식한줄짜리!!!!!! (으 펄이란 정말;;;)

  15. 공성식 Avatar
    공성식

    abraxsus님, 저도 아직 모르는 게 많지만 루비의 홍보를 위해 도와드릴게요.

    1)
    블록을 인자로 넘길 때는 두 가지 방법이 있습니다.
    블록 자체를 그대로 넘기는 방법과 Proc 객체로 바꿔서 넘기는 방법입니다.
    첫번째 방법은 암묵적인 인자이고 두번째 방법은 명시적인 인자입니다.
    암묵적일 경우엔 맨 마지막에 블록 인자가 있다고 가정하는 것입니다.
    그러므로 인자의 이름이 없습니다.
    그리고 단 하나만 가능하죠.
    만약 여러 개의 블록을 인자로 넘기고 싶으면 Proc으로 변경하고 일일이 이름을 주는 방법을 써야 합니다.

    def f &b1, &b2
    b1.call
    b2.call
    end

    2)
    &blk와 yield는 1)에서 설명한 것처럼 서로 exclusive하게 사용된다고 생각하는 게 좋습니다.
    block은 code의 literal이라고 보시면 되고 Proc은 block을 객체로 바꾼 것입니다.
    block이 더 빠르기 때문에 특별한 이유가 없다면 그냥 block을 사용하는 게 좋습니다.

    3)
    f 1, {|n| puts n} 에서 콤마(,)는 필요 없습니다.
    블록은 그 자체로 구분이 가능하므로 ,를 빼고 사용하시면 됩니다.
    f 1 do |n|
    puts n
    end
    와 같이 사용하셔도 됩니다.

    l[2] = {|n| puts n}
    블록은 객체가 아니므로 그 자체를 어떤 변수에 할당할 수 없습니다.
    이럴 경우엔 Proc으로 바꿔서 할당하시면 됩니다.
    l[2] = lambda {|n| puts n}

    4)
    s1_push와 s1_pop은 Proc 객체입니다.

    7)
    $가 붙은 변수는 전역변수입니다.
    루비는 순수객체지향언어이므로 전역변수의 사용은 극히 드물다고 할 수 있습니다.

    8)
    class의 생성이 아니라 object의 생성을 말씀하신 거죠?
    보통은 new를 사용하지만 그렇지 않은 경우도 있습니다.
    예를 들면 File.open 같은 경우입니다.
    물론 Array, Hash, String, Number 등은 literal 이 있으므로 new를 안 써도 되구요.

    Dynamic 언어의 선택에 관해 제 의견을 말씀드릴까 합니다.

    다른 언어도 많지만 주요 언어는 역시 Perl, Python, Ruby 이렇게 세 개가 아닐까요?

    Perl은 가장 먼저 시작되어 커뮤니티, 라이브러리 등이 강하지만 신택스가 너무 안 좋다고 생각합니다.
    사실 Ruby는 많은 부분을 Perl에서 가져왔지만 신택스를 훨씬 쉽게 고쳤지요.
    또한 Perl은 객체지향과는 좀 거리가 있습니다.
    만약 객체지향을 선호하신다면 단연 Ruby죠.

    저는 약 1년 동안 Python이 가장 좋은 언어라고 생각하며 지낸 적이 있기 때문에 Python과 Ruby의 비교에 있어서 좀 더 자신있게 말씀드릴 수 있을 것 같습니다.
    Python의 가장 큰 특징은 역시 significant white space라고 할 수 있습니다.
    또한 신택스에 있어서도 대체적으로 한 가지 방법만을 제시합니다.
    이런 두 가지 이유로 누가 코드를 작성했건 간에 거의 비슷하게 보입니다.
    처음에는 이것이 매우 매력적으로 보입니다.
    그렇지만 점점 불편함을 느끼게 되지요.
    일례로, 웹 개발을 Python으로 하게 될 경우 html 에 python 코드를 embed하게 되지요.
    이럴 때 indent를 하기가 무척 곤혼스러워집니다.
    또한 코딩에서의 내공이 쌓여가도 그걸 코드에 반영하는 데 제약이 많습니다.
    루비의 경우엔 코드만 봐도 작성자의 내공을 대충 알 수 있거든요.
    물론 이건 주관적인 견해에 해당하겠습니다만…
    우리가 말을 할 때도 어린이와 어른이 쓰는 말이 다르듯이 뭔가 높은 차원으로 갈 수 있는 길이 있어야 한다고 생각합니다.

    처음 파이썬에서 루비로 옮겨왔을 때 루비의 다양한 신택스와 메소드들에 주눅이 들었습니다.
    그렇지만 일단 익숙해지고 나니 파이썬보다 훨씬 짧은 코드로 작성이 가능하고 코드에 저만의 개성을 심을 수 있게 되더군요.

    결론적으로 저는 루비를 적극 권합니다.

  16. abraxsus Avatar

    으음! 공성식님의 자세한 답변과 의견 감사드립니다. :-)
    기대하지 못했던 자세한 답변에 감동.. ^^;;
    그래서인지 루비에 빠져들고 있읍니다.
    elegant하네요. ㅎㅎ

Leave a Reply

Your email address will not be published. Required fields are marked *