워드프로세서 버리고 Markdown 줍기
Markdown
John Gruber가 만든 마크업 언어입니다. 이 발표 자료도 Markdown으로 작성했습니다! 문법이 투명하여 컴파일하지 않은 평문 텍스트 자체로도 가독성이 높은 것이 특징입니다.
문법이 투명하다는 것이 무슨 뜻일까요? Markdown의 문법은 메일링리스트에서 자주 사용되는 서식들로부터 가져왔습니다. 예를 들어 메일에서 인용을 할 때 문장의 왼쪽 처음에 >를 추가하는데, Markdown의 인용 문법은 그것을 그대로 사용합니다. 강조를 할 단어는 *나 _로 감싸고, 가로줄을 추가할 때는 단순히 -----와 같이 긴 줄을 그리는 식으로 표현합니다. 제목 역시 다음과 같이 씁니다.
H1 Title
========
H2 Title
--------
이런 식으로, 평문 자체도 사람이 보기에는 서식이 느껴지기 때문에, 잘 작성된 Markdown 문서는 HTML 등으로 번역하기 이전의 평문 텍스트로도 매우 예쁘고 읽기 쉽게 보입니다. 이 발표 자료의 원문 평문 텍스트를 한번 보세요,
Markdown에 표(tables), 정의 목록(definition lists), 약자(abbreviations), 각주(footnotes) 등의 추가적인 서식을 더 추가한 명세입니다.
PHP Markdown Extra, Pandoc 등의 주요 구현들이 이것을 구현하고 있습니다.
주요 구현들
- Markdown
- Markdown을 디자인한 John Gruber가 Perl로 작성한 최초 구현.1
- PHP Markdown
- Markdown Extra를 디자인한 Michel Fortin이 PHP로 작성한 버전. 아래 언급한 Pandoc을 제외하면 가장 정확한 처리를 합니다.
- Maruku
- Ruby로 작성된 구현으로, 확장 문법을 추가하기 쉽습니다.
- Pandoc
- Haskell로 작성된 버전. 가장 정확하고 빠른 구현. 내부적으로 문서 트리를 생성하는 식으로 작동합니다.
Io 소개
Steve Dekorte가 만든 최소주의적 디자인의 프로그래밍 언어입니다. 많은 부분에서 Lisp을 계승하여 리엔지니어링했습니다. Io 구현은 아래 사이트에서 구할 수 있습니다.
http://iolanguage.com/
현재는 ANSI C로 작성된 단 하나의 구현만 존재합니다.
특징
- 예약어 전혀 없음
- 연산자도 없음 (특정 식별자의 우선 순위를 런타임에 맘대로 바꿀 수 있음)
- 프로토타입 기반 객체 지향 프로그래밍
- Homoiconicity (Lisp과 같은 데이터로서의 코드)
- Actor 기반 동시성 프로그래밍
- 작은 사이즈, 높은 이식성 (100% ANSI C로 작성됨)
- 임베드하기 쉬움
설치
Windows에서는 .exe 파일로 컴파일된 바이너리를 찾아서 받습니다.
http://homepage.mac.com/jamesrburgess/Stuff/
나머지 플랫폼에서는 소스 코드를 컴파일하여 설치합니다. 일반적인 소스 컴파일 방법과 크게 다르지는 않습니다.
$ io
io: error while loading shared libraries: libiovmall.so: cannot open shared
object file: No such file or directory
위와 같은 오류가 나는 분들은 ld 경로에 /usr/local/lib 디렉토리를 추가하시면 됩니다.
기본적인 문법
Io의 메세지 문법은 Lisp의 S-expression과 마찬가지로 문법이 없다시피한 최소한의 규칙만을 갖습니다.
receiver method(a, r, g, s)
리시버가 생략되면 현재 문맥(context) 객체의 슬롯(slot)을 찾습니다.
method(args)
인자가 없을 경우 괄호를 생략할 수 있습니다.
method()
method
연사자가 있긴 하지만 일반 메서드와 다른 것은 없습니다.
Io> 1 + 2
==> 3
Io> 1 +(2)
==> 3
계산기로 쓰기
REPL을 제공하는 다른 언어들과 마찬가지로 Io도 계산기처럼 쓸 수 있습니다.
Io> 123 + 456
==> 579
Io> 123 - 12
==> 111
Io> 12 * 17
==> 204
Io> 55 / 4
==> 13.75
주요 객체들
nil
- Booleans:
true, false
- Numbers:
2, -5, 3.14
- Strings:
"string"
- Lists:
list(2, -5, "string", nil, true, false)
- Lambda:
method(a, b, a + b)
프로토타입 기반 객체 지향 언어 (prototype-based object orientation)
우리가 사용하는 대부분의 객체 지향 언어들은 클래스(class)를 상속(inheritance), 실체화(instantiation)하는 개념을 기본으로 합니다. Io는 클래스 기반의 객체 지향 언어가 아니라 프로토타입 기반의 객체 지향 언어로, 클래스라는 것을 배제한 상태에서 객체 지향 프로그래밍을 합니다.
Io에서는 클래스와 인스턴스를 나누지 않고 대신 객체만 존재합니다. 구현 상속과 실체화를 하는 대신 복제(cloning)라는 것을 쓰며 타입이 없습니다.
| 프로토타입 기반 OO |
클래스 기반 OO |
| 객체, 원형 |
클래스 |
| 객체 |
인스턴스 |
| X의 원형 |
X의 클래스 |
| X를 복제한 객체 |
X의 인스턴스 |
| 복제 |
상속 |
| 복제 |
실체화 |
| 원형 |
수퍼클래스(superclass) |
| 복제된 객체 |
서브클래스(subclass) |
객체 만들기
Shape := Object clone do(
draw := method(...)
)
Triangle := Shape clone do(
draw := method(...)
)
Rectangle := Shape clone do(...)
Circle := Shape clone do(...)
aRectangle := Circle clone do(
x := 5
y := 10
width := 100
height := 150
color := Color clone do(
red := 0
green := 0
blue := 0
)
)
피보나치 수 (Fibonacci number)
Number fibonacci := method((self - 1) fibonacci + (self - 2) fibonacci)
1 fibonacci := 1
0 fibonacci := 0
다형성(polymorphism)? 오버로드(overloading)? 특수화(specialization)?
지연 평가 (lazy evaluation)
Io의 메서드는 기본적으로 인자의 표현식을 평가하지 않고 Message 객체 형태로 전달합니다.
define := method(
name := call message argAt(0) name
value := call message argAt(1) doInContext(call sender)
call sender setSlot(name, value)
value
)
위와 같이 정의한 define 메서드는 아래처럼 사용할 수 있습니다.
Io> define(pi, 3.14)
==> 3.1400000000000001
Io> pi
==> 3.1400000000000001
Io> define(abc, pi * 100)
==> 314
Io> abc
==> 314
어떻게 저런 식으로 돌아갈 수 있는 걸까요? 주요 객체에 대해 설명을 하겠습니다.
call (Call)
- 호출에 관한 정보를 담는
Call 객체.
Call sender (Object)
- 메세지를 보낸 쪽 객체. 즉 호출한 쪽의 문맥.
Call message (Message)
- 호출하는 표현식을 담는
Message 객체. 이 경우에는 message(define(pi, 3.14))나 message(define(abc, pi *(100))).
Message arguments (List)
- 호출하는 메세지의 인수 리스트. 평가되지 않은
Message 객체의 목록. 이 경우에는 list(pi, 3.14)나 list(abc, pi *(100)).
Message argAt (Message)
call message arguments at의 줄임.
Message doInContext (Object)
- 인자로 넘겨진 객체를 문맥으로 하여 메세지를 호출.
Lisp과 비교하자면?
Message 객체는 코드를 담습니다. Lisp으로 치자면 리스트입니다.
message 함수는 Lisp의 quote와 같습니다.
Io> message(abc(a, b, c))
==> abc(a, b, c)
Io> message(abc(a, b, c)) arguments
==> list(a, b, c)
Io> message(abc(a, b, c)) name
==> abc
Message doInContext 메서드는 Lisp의 eval과 같습니다.
Io> context := Object clone do( a:= 123; b := 456 )
==> Object_0x1018c0990:
a = 123
b = 456
Io> message(a + b)
==> a +(b)
Io> message(a + b) doInContext(context)
==> 579