2

Lisp はホモイコニックです。つまり、コードをデータとして扱うことができます。実行時にこれを可能にする実装はどれですか? 以下は、疑似コードでの意味の例です。

(defun (my-func)
  (display "foo ")
  (display "bar ")
  (display "baz "))

(defun (main-loop)
  (my-func)
  (swap (first my-func) (second my-func))
  (main-loop))

これにより、「foo bar baz bar foo baz」が繰り返し出力されるはずです。

4

3 に答える 3

3

これはおそらく最もエレガントなアプローチではありませんが、一般的な Lisp では次のようなことができます。

> (setq f '(defun foo () (princ "foo ") (princ "bar ") (princ "baz ")))
(DEFUN FOO NIL (PRINC "foo ") (PRINC "bar ") (PRINC "baz "))
> (eval f)
FOO
> (foo)
foo bar baz
NIL
> (defun frot ()
        ; Call foo (stored in f)
        (funcall (eval f))
        ; Swap the 1st and 2nd statements in foo
        (setf tmp (cadddr f))
        (setf (cadddr f) (cadr (cdddr f)))
        (setf (cadr (cdddr f)) tmp)))
FROT
> (frot)
foo bar baz
(PRINC "foo ")
> (frot)
bar foo baz
(PRINC "bar ")
> (frot)
foo bar baz
(PRINC "foo ")

これは Lisp 関数をin situfで実行するのではなく、 in に格納しますが、Lisp プログラム自体が動的に操作および実行できる Lisp データ構造であるという事実を示しています。

于 2014-01-10T03:33:24.450 に答える
1

説明どおりにコードを変更している場合は、コードの構造についてある程度知っています。コードの構造がわかっているので、その構造をパラメータ化できます

(define (foo-er foo bar baz)
  (lambda ()
     (display foo)
     (display bar)
     (display baz)))

次に、引数を次のように明示的に渡すことで、スワップを行うことができます。

(define (main-loop)
  (let looping ((foo "foo ") (bar "bar ") (baz "baz "))
    ((foo-er foo bar baz))
    (looping bar foo baz)))

> (main-loop)
foo bar baz bar foo baz foo bar baz ...

CommonLisp バージョンも同様です。

あなたが周りにいる必要がある場合my-func

(define my-func #f)
(define (main-loop)
  (let looping ((foo "foo ") (bar "bar ") (baz "baz "))
    (set! my-func (foo-er foo bar baz)
    (my-func)
    (looping bar foo baz)))
于 2014-04-07T14:34:59.957 に答える