지금 읽고 있는 “Object Thinking”에서 자주 사용되는 예제가 Smalltalk이다보니, 가끔씩 Smalltalk code를 읽을 일이 생겨서, I Can Read C++ and Java But I Can’t Read Smalltalk란 article을 읽어보았다. 말그대로, C++/Java 와 같은 문법에 익숙한 프로그래머가 Smalltalk code 앞에서 적어도 문맹은 되지 않도록 해주는 글이다.
Smalltalk 언어는 Object-Oriented Programming Language의 시조라고 할 수 있는 Simula의 첫번째 아들격으로, 1979년에 태어나, 최근에 만들어진 여러 OOPL 들(Objective-C, Java, Ruby, …)의 아버지 역할을 하면서, 아직도 Pure OOPL의 강력한 정신적 지주로 군림하고 있다. 여기서는 언어의 철학적인 특질(OOP)이나 구현에 관련된 특성(garbage collection, …)은 피하고, 단지 다른 언어들(C++, Java, …)에 비해 문법적으로 특이한 점을 짚어보자.
No parentheses/Keywords
t->rotate (a, v); // C++
t rotateBy: a around: v // Smalltalk
Smalltalk에서는 receiver(object)와 message(method)간의 구분을 위해 따로 operator를 쓰지 않고 space를 사용한다. method 이름이나 parameter 이름과 argument들을 구분할 때도, 괄호를 사용하지 않고, space와 colon을 사용한다. 이 때, method 이름이나 parameter 이름은 keyword라고 부르고, keyword를 조합해서 method를 호출하기 때문에, parameter들의 순서를 신경쓸 필요도 없고, readability를 상당히 향상시킨다. (C++, Java code를 읽을 때 힘든 점이, argument가 무엇을 의미하는 지 모른다는 점이니까) 대신 프로그래머는 약간의 고생을 해야하긴 하지만, 오히려 프로그래머가 정확한 semantic을 이해할 수 있다는 점에서, “example code의 폐해”를 줄일 수 있는 면도 있다.
Getter/Setter method
// C++
long getAge () { return age; }
void setAge (long newAge) { age = newAge; }
// Smalltalk
age ^age
age: newAge age := newAge
요즘에는 Python이나 Ruby, C# 같은 유명한 언어들에서 모두 지원하는, 워낙 일반적인 문법이 되어서 따로 언급할 필요는 없겠지만, Smalltalk 에 이미 있던 문법이라는 점은 특기할만하다. Smalltalk 이전에도 있던 문법일까? 그리고 Smalltalk에서도 default getter/setter를 지원하는지도 궁금하다.
Block
a = f (x) { return x + 1; } // C-Like syntax
a := [:x | x + 1] // Smalltalk
Smalltalk에서는 Block을 통해서 Higher Order Function을 지원한다. 때로는 Closure라는 이름으로 불리기도 한다. (어원이 어느 곳인지는…) C/C++에서는 function pointer의 형태로 이를 간접적으로 지원하지만, Smalltalk에는 Block이라는 이름의 function object가 존재한다. Block은 callback이나 collection의 enumeration 등 매우 쓸모가 많다. Python이나 Ruby, C# 같은 현대의 Programming Language들에서는 모두 직접 지원하는 문법이다.
Conclusion
현대의 여러 Programming Language의 Object-oriented programming paradigm 이나, 위에서 소개한 문법적인 요소들, 그리고 구현에 이르기까지, 많은 요소들이 Smalltalk로부터 전해져 내려왔다. (물론 그 중에서도 어떤 것들은 더욱 오랜 역사를 가지고 있다; 수학적인 개념들부터 상속된 것들이 특히 그러하다) 이러한 역사를 모르는 사람들은 때로 Programming Language에 대한 이상한 오해를 가지기도 한다. 미신을 멀리하고 역사를 배우라.
Smalltalk 블로그를 만들려고 하다가 검색하던 중에 님의 글을 보게 되었습니다. 반갑네요. ^^
두 가지만 첨언합니다.
우선 블록에 대해서… Lisp 계열의 언어를 제외하고는, Algol-like 언어에서는 Smalltalk의 Block을 그대로 구현해 낸 언어는 보기 드뭅니다. 예로 드신 C#에서는 deligate라는 것을 지원하고는 있지만 역시 Block보다 번잡스럽습니다. Python이나 Ruby에서는 어떤지 모르겠지만, Block을 Smalltalk 답게 구현한 언어는 Smalltalk 밖에 없다고 알고 있습니다. ^^
Default property에 대해서… 음, Delphi에서는 배열 프로퍼티를 만들 때 일일이 프로퍼티의 이름을 붙여줄 필요 없이 생성된 인스턴스에 바로 인덱스를 붙여줄 때 사용했었는데요, 다른 언어에서는 default property가 어떤 의미인지 잘 모르겠네요. Smalltalk에서는 property라는 개념이 없고, 단지 수신자(receiver)에게 메시지를 전달해서 수신자가 가지는 인스턴스 변수에 접근하는 개념이니 음.. 따로 default property가 필요치 않을지도 모르겠습니다. 만약 인스턴스 변수 중에 배열이 있다면 Smalltalk에서는
receiver array at: 1 put: ‘Hi’.
이런 방법을 사용하거든요.
제 블로그가 아직 많이 부족합니다. 하지만 조금씩 업데이트 하고 있으니, 관심 있으시면 방문해 주십시오.