Search Results for '루비'

5 POSTS

  1. 2008/03/28 정적 타이핑과 동적 타이핑
  2. 2007/02/18 Ruby 변수 생성
  3. 2006/12/25 Prototyped-based Programming (3)
  4. 2006/12/12 I hate Ruby's special global variables
  5. 2006/09/20 Mixin (2)

정적 타이핑과 동적 타이핑

Posted 2008/03/28 02:54
마이크로소프트의 IronRuby 팀에서 No Borg-like release train for Ruby on .NET 이라는 글을 통해 올해 말까지는 IronRuby 1.0을 완성하겠다는 발표를 했습니다. 루비가 제대로 된 언어 명세도 없다보니 명확한 시멘틱이 정의가 안 된 부분이 많고 구현마다 다른 부분을 어려움으로 호소하고 있습니다. 아 그리고 루비의 가장 중요한 어플리케이션이 Rails인 만큼 IronRuby on Rails도 중요하게 생각하고 있는 것 같습니다.

그런데 이 글의 마지막 문구에서 왜 .NET 개발자가 루비에 관심을 가져야 하느냐는 질문에 Iron Ruby 프로젝트 리더인 John Lam 말이 정적 타이핑(static typing)하는 언어는 동적 타이핑(dynamic typing)하는 언어보다 유지보수 하기가 힘들다는 말을 했습니다. 유지 보수가 힘든 이유는 변경이 힘들기 때문이라고 이야기했습니다.


Finally, why should .NET developers bother with Ruby? According to Lam: "You spend less time writing software than you spend maintaining software. Optimizing for writing software versus maintaining software is probably the wrong thing to do. Static typing makes it harder to maintain software because it's harder to change it."®


저는 정반대로 생각하기 때문에 순간 글을 잘못 읽었나 착각에 빠졌습니다. 이와 관련해  Haskell Cafe에도 Dynamic typing makes you more productive? 라는 글에 내용이 올라오면서 많은 사람들이 자기 생각을 달았습니다. 요약하면, C++, Java, C# 처럼 어설픈 정적 타이핑하는 언어를 보던 사람들에게는 루비의 동적 타이핑이 굉장한 장점으로 보일 수 있는 것은 사실입니다만 제대로 된 정적 타이핑을 하는 언어를 보면 그런 생각을 바꿀 것이라는 의견입니다. 물론 헤스켈 커뮤니티 메일링 리스트니깐 당연히 그렇게 이야기하겠지만요.

결론: 정적 타이핑의 이름을 더럽힌 자바랑 C# 나빠요.

Ruby 변수 생성

Posted 2007/02/18 01:02
루비에서 변수 생성에 대한 규칙을 잘못 알고 있었다.

[skyul@dev ~]$ irb
irb(main):001:0> a
NameError: undefined local variable or method `a' for main:Object
        from (irb):1
irb(main):002:0> a = 1 if false
=> nil
irb(main):003:0> a
=> nil
irb(main):004:0>

처음 irb를 동작시키면 a라는 변수(혹은 메쏘드)가 정의되어 있지 않으므로 undefiend local variable or method 'a'라는 에러 메시지를 출력한다. 다음으로 실행한 구문은 a = 1 if false이다. if false는 무조건 거짓이므로 a = 1은 절대로 실행되지 않는다. 문제는 다음 행이다. 직관적으로 판단하기에 a = 1이라는 대입(assignment)가 일어나지 않았으므로 a는 여전히 undefiend 일 것이라 생각했지만, 예상과는 달리 a = nil이다.  즉 루비는 a = 1이 대입이 일어나야만 a 변수를 생성해 주는 것이 아닌 것이다. 프로그램을 차례대로 읽으면서 조건에 상관없이 a가 변수로 사용되었음을 알았기 때문에 그 후로는 a를 정의해 준 것이다.

로컬 변수와 메쏘드를 구분하는 것도 마찬가지이다. 다음은 "Programming Ruby: The Ruby Language, Variable/Method Ambiguity"에서 따온 예제이다.

def a
  print "Function 'a' called\n"
  99
end

for i in 1..2
  if i == 2
    print "a=", a, "\n"
  else
    a = 1
    print "a=", a, "\n"
  end
end

결과

a=1
Function 'a' called
a=99


위 예제는 a가 함수로도 사용될 수 있고, 변수로도 사용될 수 있음을 보여준다. a = 1 구문을 지나고 나면 a가 변수임을 알고, 변수로 호출한다. i == 2인 경우 이미 a에 1라는 변수가 할당되어 있지만 앞쪽에 나와있기 때문에 a = 1이라는 대입이 있었음을 알지 못한다. 따라서 이 경우 a를 메쏘드로 가정하는 휴리스틱을 사용한다.

다음과 같이 i == 1 조건이 먼저 나오면 어떨까?

for i in 1..2
  if i == 1
    a = 1
    print "a=", a, "\n"
  else
    print "a=", a, "\n"
  end
end

이 경우 a = 1 대입은 i == 1인 조건에만 있지만, 이 조건이 else 구문보다 앞서 있기 때문에 둘 다 a를 변수로 인식하고 1을 출력할 것이다.

a=1
a=1

Prototyped-based Programming

Posted 2006/12/25 20:02
우리가 객체지향 프로그래밍 언어(object-oriented programming language)라고 부르는 언어 패러다임은 크게 1) 클래스 기반과 2) 프로토타입 기반의 언어로 양분할 수 있습니다. 클래스 기반 객체지향언어는 C++, 스몰토크, 자바, 루비처럼 클래스를 통해 현실 세계를 모델링하고, 클래스에서 객체(인스턴스)를 찍어내서 프로그래밍하는 모델을 말합니다. 반대로 프로토타입 기반의 언어에는 자바스크립트(JavaScript)가 있는데, 별도의 클래스 없이 이미 존재하는 객체를 클론(clone)해서 프로그램을 작성하는 방법입니다.

프로토타입 기반 언어에 대한 일반적인 비판은 동적 타이핑 언어에 대한 비판과 닮아 있습니다. 정확성(correctness), 안전성(safety), 예측성(predictability), 효율성(efficiency) 등이 떨어진다는 것입니다. [위키피디아 참고] 클래스 기반 객체지향언어에서 클래스는 외부 세계를 모델링(modeling)하는 방법일 뿐만 아니라 프로그램의 정확성을 확인할 수 있는 타입(type)이기 때문입니다. 쉽게 풀어서, 루비의 Array 클래스가 sort라는 메쏘드를 가지고 있다는 사실 자체가 클래스 사용자와 클래스 사이의 계약이 되기 때문입니다. 반대로 프로토타입 기반 언어에서는 클래스가 없기 때문에 이런 계약 관계를 쉽게 알아보기 힘들게 됩니다.

빠른 프로토타이핑(prototyping)과 개발 속도를 위해서 정적 타입 시스템(static type system)이라는 안전망을 포기한 스크립트 언어가 대부분 클래스기반 객체지향언어라는 점은 약간 의아합니다. 상업적으로 유일하게 성공한 프로토타입 언어인 자바스크립트를 제외하면, 프로토타입 언어는 Self, Cecil, Io 등 연구용 언어가 대부분이기 때문입니다. 자바스크립트의 표준인 EcmaScript조차 클래스 기반 언어로 전환을 이야기하고 있다고 합니다.

저는 개인적으로 파이썬 루비 같은 범용적 스크립트 언어면서 프로토타입에 기반한 언어가 대두하지 않을까 하는 생각을 해보기도 합니다. 동적 타이핑(dynamic typing)이라고 하지만 실제로는 타입 시스템이 없는 것이나 마찬가지인 스크립트 언어에서 굳이 클래스 기반 언어를 고집할 이유가 없기 때문입니다. 물론 객체지향 모델링 방법이나 베스트 프랙티스 등이 모두 클래스 기반 언어를 중심으로 논의되어 왔고, 기존 개발자들이 프로토타입 기반 객체지향 언어에 익숙하지 않다는 문제점이 있기는 합니다. 하지만 현재의 스크립트스러움을 극단으로 몰고 가려면 클래스 보다는 오히려 프로토타입이 아닐까요?

I hate Ruby's special global variables

Posted 2006/12/12 01:12
I think the reason why Ruby is not so readable is because Ruby has special variables like $$.

$! latest error message
$@ location of error
$_ string last read by gets
$. line number last read by interpreter
$& string last matched by regexp
$~ the last regexp match, as an array of subexpressions
$n the nth subexpression in the last match (same as $~[n])
$= case-insensitivity flag
$/ input record separator
$\ output record separator
$0 the name of the ruby script file
$* the command line arguments
$$ interpreter's process ID
$? exit status of last executed child process

Ruby programmers who often use these awkward looking special variables may feel comfortable, but I hate that I have to memory the difference between $! and $@. What is the rule to memorize the meanings of these variables? Even worse, some variables names are confusing. For example, Ruby naming convention states that variables starting with $ are global variables, but $_ and $~ are closer to local variables.

Ruby emphasizes the principles of least surprise, but special variables really surprised me. [For those of you who are not familar with the principles of least surprise: Read"Applying the Rule of Least Surprise"  in The Art of Unix Programming written by Eric  Raymond.]

Ruby is a pure objected-oriented language and special variables do not fit well in OO concepts. Why don't we make a Process clsss and define pid and args methods to retrieve process ID and command line arguments instead of ugly $$ and $* variables?

Mixin

Posted 2006/09/20 03:42
믹스인(mixin)은 일반적으로 스크립트 언어에서 다중 상속을 대신하는 방법으로 자주 쓰인다. 일반적으로 다중 상속을 사용하는 이유가 코드를 상속받기 위해서인데, Mixin은 클래스 계층을 변경하지 않고 코드만 포함시키는 방법을 제공하기 때문이다. 믹스인을 제공하는 대표적인 스크립트 언어가 루비인데, 다음 루비 프로그램을 살펴보자.


module Debug

  def whoAmI?

    "#{self.type.name} (\##{self.id}): #{self.to_s}"

  end

end

class Phonograph

  include Debug

  # ...

end

class EightTrack

  include Debug

  # ...

end

ph = Phonograph.new("West End Blues")

et = EightTrack.new("Surrealistic Pillow")

ph.whoAmI?       »       "Phonograph (#537766170): West End Blues"

et.whoAmI?       »       "EightTrack (#537765860): Surrealistic Pillow"

[http://www.rubycentral.com/book/tut_modules.html에서 발췌]


위에서 Phonograph와 EightTrack라는 두 가지 클래스를 정의했는데, 각각은 Debug 모듈을 임포트하고 있다. 루비언어는 클래스 내에서 모듈을 임포트할 경우 모듈 내의 함수가 자동으로 클래스의 메쏘드로 변환된다. 따라서 includeDebug라고 써주는 것만으로 두 클래스는 ph.whoAmI라는 메쏘드가 정의되게 된다. 즉 클래스 계층을 변화시키지 않고 코드만 재활용할 수 있는 것이다.