lisp언어에서 데이터를 코드로 사용한다는게 뭔지..

gurugio의 이미지

요즘들어 부쩍 프로그래밍에 대해 한계가 느껴져서
고민중이고 시험삼아 Lisp를 공부하고 있습니다.
만들어본 코드는 늘어나는데 생각을 코드로 뽑아내는데 한계가 느껴지는것 같기도 하고
제가 만든 코드를 볼때 뭔가 뻔하다는 생각만 듭니다.

lisp 언어에서 데이터를 코드로 사용한다? 데이터가 코드로 변환된다?
정확히 어떤 의미인지 몰라서 말로도 표현하기 힘든
그런게 가능하다고 해서 실험을 해봤습니다.
결과적으로 실험을 해놓고도 아직 정확한 실험인지 제가 뭘 실행한건지도 모릅니다만
저에게는 신선한 충격이라서 기록을 위해 남깁니다.

1. ret-plus 함수 정의

[32]> (defun ret-plus (x) (if x '+ '-))
RET-PLUS
[33]> (ret-plus t)
+

ret-plus라는 함수는 참을 인자로 주면 +라는 심볼을 반환하고 거짓이면 -라는 심볼을 반환합니다.

(lisp에서는 심볼이라고 하는것 같습니다.
C에서 '+'와 같은 것인줄만 알았는데 이 실험으로 같은게 아닌것 같다고 생각하고 있습니다.)

2. 리스트 타입의 데이터 생성

[34]> (list (ret-plus t) 4 3)
(+ 4 3)

list라는 함수의 인자로 함수 호출을 넘겼습니다. 함수의 인자가 함수 호출이 되는 것은
C에서도 가능하므로 함수 인자로 넘기는 데이터가 함수 호출이라는 코드가 되는 것인지
함수 인자로 넘기는 데이터가 함수 호출의 값이 되는 것인지는 불명확한것 같습니다.

3. 데이터를 evaluation

[35]> (eval (list (ret-plus t) 4 3))
7

마지막으로 eval이라는 리스트 처리? 함수를 호출했습니다.
이 코드는 이렇게 변환됩니다. (list (ret-plus t) 4 3) 의 결과값은 분명히 리스트타입의 데이터입니다.
그런데 eval 이라는 함수에 전달하자 eval은 데이터를 코드로 실행해버렸습니다.

4. 결과 해석

C에서 int arr[3] = {'+', 3, 4} 라는 배열이 있을 때, 배열이 자체적으로 실행되지는 않습니다.
eval 함수를 만드려면 if (arr[0] = '+') ........ 등으로 만들어서
배열을 처리하는 코드를 따로 만들어야 합니다.
따라서 C에서 eval 함수를 만드려면 배열의 첫 항목을 가능한 모든 함수 이름과 비교해야하는데
이건 사실상 불가능합니다. 그럴 필요도 없구요.
그런데 lisp에서는 리스트라는 타입의 데이터가 그대로 실행되었습니다.

정확한 실험인지는 모르겠습니다.
옛날 중학교때 take와 get의 차이를 이해못하고 아직까지도 모르고 있는게 생각났습니다.
Paul형님의 책 첫머리에서 C/C++이라는 언어의 한계를 벗어나는 표현이 가능하다는
설명이 있는데 굉장히 아리송한 느낌이 들고 있습니다.
데이터가 그 자체로 코드로 실행된다라...전혀 멍하네요.
여긴 어디? 난 누구?

댓글

ifree의 이미지

LISP 에서 말하는 Code as Data 패러다임이라는 것은 코드를 데이타처럼 써서 함수가 함수의 인자가 되거나 함수의 리턴 값이 될 수 있다는 것을 의미합니다.

예를 들어 다음 함수는 함수를 1에 적용했을 때 그 값이 증가하는지의 여부를 알아보는 함수인데
(코드 형식은 LISP 의 방언인 Clojure 입니다. 표현양식이 다소 다릅니다.)

(defn inc1? [f]
(if (> (f 1 1) 1) "1 is increased!" "1 is not increased."))

이 함수에 + 나 * 를 인수로 해서 적용하면

(inc1? *)

"1 is not increased."

(inc1? +)

"1 is increased!"

와 같은 결과를 얻습니다.

위와 같이 함수가 함수의 인수가 되거나 함수가 함수의 결과값이 될 수 있으며 또한 마크로를 이용하여 언어의 확장이 가능하기 때문에 LISP 는 다양한 기능을 재유로이 추가할 수 있는 마치 트랜스포머와 같은 언어라고 합니다.

feanor의 이미지

Quote:
LISP 에서 말하는 Code as Data 패러다임이라는 것은 코드를 데이타처럼 써서 함수가 함수의 인자가 되거나 함수의 리턴 값이 될 수 있다는 것을 의미합니다.

이것은 일급 함수(first-class function)의 설명이지 Code as Data의 설명이 아닙니다.

hongminhee의 이미지

code as data는 코드 자기 자신의 AST를 런타임에 데이터로 다룰 수 있다는 뜻입니다. 말씀하신 것은 람다(lambda)에 대한 설명입니다.

홍민희 (VLAAH, LangDev)

redneval의 이미지

slee0303님이 언급하신 것은 `고차함수'의 개념입니다.

(Code as Data 와는 거리가 먼) 하스켈로 나타내면 다음과 같습니다.

inc1 f = if f 1 1 > 1 then "1 is increased!" else "1 is not increased."

여기서 inc1 은 함수를 인자로 받는 고차함수입니다.
실행결과는 다음과 같습니다.

Prelude> inc1 (*)
"1 is not increased."
Prelude> inc1 (+)
"1 is increased!"

--------------------Signature--------------------
Light a candle before cursing the darkness.

M.W.Park의 이미지

일단은 (시작하는 입장에서) 간단하게 생각하세요.


  1. 모든게 list이다.

  2. list를 REPL에 입력하면 결과를 받는다.


그리고 symbolic language를 공부할 때는 그냥 그 자체로 받아들이는 것이 좋을 때가 많습니다.
패러다임 또는 태생적 디자인이 다른 언어를 비교하기 시작하면 머리에 쥐가 납니다, ^^;

-----
오늘 의 취미는 끝없는, 끝없는 인내다. 1973 法頂

-----
오늘 의 취미는 끝없는, 끝없는 인내다. 1973 法頂

gurugio의 이미지

그러게요. 답글달아주신 분들 설명을 봐도 므흣할 뿐이네요 ;-)

----
섬기며 사랑하면 더 행복해집니다.
몸에 좋은 칼슘이 듬뿍담긴 OS 프로젝트 - 칼슘OS http://caoskernel.org

박영만의 이미지

매번 느끼는 거지만 참말 대단하세요.
회사 다니면서 게다가 결혼까지 하시고는 어떻게 그렇게 공부를 하시는지...
게으른 제가 참말 부끄럽습니다. ㅠㅡㅠ

죠커의 이미지

결국 data as code에 대한 상세한 설명은 이 쓰레드에선 이뤄지지 않았네요 (먼산)

솔직히 이 쓰레드의 토론을 통해서 모르는 사람이 이해하긴 힘든 것 같고요.

나중에 시간을 내어서 정리된 글을 올려보겠습니다.

- 죠커's blog / HanIRC:#CN

semmal의 이미지

따지고 들자면 상당히 복잡하게도 어쩌면 단순하게도 설명할 수 있겠지만, 윗 분 말씀대로 그냥 있는데로 받아들이는게 가장 좋다고 생각합니다.

애초에 다른 언어를 몰랐다면 그런가보다 했을 일인데... 그래서 "모르는 게 약"이라는 말이 생긴건지도 모르지요.
------------------------------
How many legs does a dog have?

------------------------------
How many legs does a dog have?

redneval의 이미지

통상적인 프로그램은 데이터를 다루고,
컴파일러(또는 인터프리터)는 코드를 다룹니다.

`모든 것은 리스트'인 scheme(혹은 lisp 및 그의 방언)에서
코드도 리스트이고, 데이터도 리스트이므로,
코드와 데이터가 동일한 형태(리스트)를 가지고, 둘을 다루는 방법도 거의 같습니다.

(주의! : 설명의 편의상 프로시저와 매크로를 구분없이 함수라고 부르겠습니다.
하지만 둘은 실제 기능상에서 차이가 있으므로 더 자세히 공부할 때는 둘을 잘 구분하기 바랍니다.)

그러면 리스트를 코드로 해석할지 데이터로 해석할지를 알려주는 기능이 필요합니다.
quote함수는 코드를 코드로 해석하지 않고 데이터로 해석하도록 알려줍니다.
반대로 eval함수는 코드로 해석하도록 강제합니다.

; 실행환경 : DrScheme (R5RS)
> (define (two_times x) (* 2 x))
> (two_times 2)
4

two_times는 함수로 해석되지만

> two_times
#<procedure:two_times>

quote를 붙여주면 코드를 데이터로 보게 됩니다.

> (quote two_times)
two_times
> 'two_times
two_times

문자열과는 다릅니다.

> "two_times"
"two_times"

함수에 quote를 붙인 것을 심볼이라고 합니다.

심볼, 문자열, 함수는 상호변환이 가능합니다.

> (symbol->string (quote two_times))
"two_times"
> (string->symbol "two_times")
two_times
> (eval (quote two_times) (interaction-environment))
#<procedure:two_times>
> (define (eval_str x) (eval (string->symbol x) (interaction-environment)))
> ((eval_str "+") 1 1)
2


통상적인 프로그램은 데이터를 다루고,
컴파일러는 코드를 다룬다고 하였습니다.
그러므로 코드를 데이터처럼 다룰 수 있는 scheme에서는 컴파일러의 능력도 일부 가지고 있습니다.

그러니 문법을 정의하는 함수인 define-syntax가 있다는 것은 자연스러운 일입니다.

다음은 if-then-else라는 문법을 정의하는 예입니다.

> (define-syntax if/
      (syntax-rules (then ow)
         ((_ cond then x else y)
          (if cond x y))))
> (if/ 1 then 2 else 3)
2

사실은 `문법을 정의한다'라고 하지는 않고, `매크로를 정의한다'라고 합니다.
코드와 데이터가 동등한 마당에, 문법과 함수가 같은 것이라 해도 그리 놀랍지는 않을 것입니다.

이번에는 재미있는 매크로 하나를 만들어봅시다.

> (define-syntax display_code
      (syntax-rules ()
        ( (_ code)
          (begin
            (display (quote code))
            (display "\n==> ")
            (display code)))))
> (display_code (+ 1 1))
(+ 1 1)
==> 2

display_code라는 함수는,
코드를 받아서, 코드 그 자체를 출력하고 그 다음은 계산 결과를 출력합니다.
이것는 code-as-data 기능이 없는 다른 언어에서는 흉내내기 힘든 것입니다.
(perl 등의 언어에는 eval함수가 있지만, 그것은 문자열을 인자로 받습니다.
코드를 원래의 형태 그대로 인자로 받을 수 있는 scheme과는 큰 차이가 있습니다.)

--------------------Signature--------------------
Light a candle before cursing the darkness.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.