この記事によると、次のLispコード行は「Hello world」を標準出力に出力します。
(format t "hello, world")
ホモイコニック言語であるLispは、次の方法でコードをデータとして扱うことができます。
ここで、次のマクロを作成したと想像してください。
(defmacro backwards (expr) (reverse expr))
backwardsはマクロの名前で、式(リストとして表される)を取り、それを逆にします。もう一度、「Hello、world」で、今回はマクロを使用しています。
(backwards ("hello, world" t format))
Lispコンパイラはそのコード行を見ると、リストの最初のアトム(
backwards
)を見て、マクロに名前を付けていることに気付きます。未評価のリスト("hello, world" t format)
をマクロに渡し、マクロはリストをに再配置します(format t "hello, world")
。結果のリストはマクロ式を置き換え、実行時に評価されるものです。Lisp環境は、最初のアトム(format
)が関数であることを確認し、評価して残りの引数を渡します。
Lispでは、コードがリスト(s-expressions?)として実装されているため、このタスクを達成するのは簡単です(間違っている場合は修正してください)。
次に、このOCaml(ホモイコニック言語ではない)スニペットを見てください。
let print () =
let message = "Hello world" in
print_endline message
;;
OCamlにホモイコニシティを追加するとします。OCamlはLispと比べてはるかに複雑な構文を使用します。どうしますか?同種性を実現するために、言語は特に簡単な構文を持っている必要がありますか?
編集:このトピックから、Lispのものとは異なるホモイコニック性を達成する別の方法を見つけました:io言語で実装されたもの。この質問に部分的に答えるかもしれません。
ここでは、簡単なブロックから始めましょう。
Io> plus := block(a, b, a + b) ==> method(a, b, a + b ) Io> plus call(2, 3) ==> 5
さて、ブロックは機能します。プラスブロックは2つの数字を追加しました。
では、この小さな仲間について内省してみましょう。
Io> plus argumentNames ==> list("a", "b") Io> plus code ==> block(a, b, a +(b)) Io> plus message name ==> a Io> plus message next ==> +(b) Io> plus message next name ==> +
熱い聖なる冷たい金型。ブロックパラメーターの名前を取得できるだけではありません。また、ブロックの完全なソースコードの文字列を取得できるだけではありません。コードに忍び込み、内部のメッセージをたどることができます。そして何よりも驚くべきことです。それは非常に簡単で自然なことです。イオの探求に忠実。Rubyのミラーはそれを見ることはできません。
しかし、おっ、今、そのダイヤルに触れないでください。
Io> plus message next setName("-") ==> -(b) Io> plus ==> method(a, b, a - b ) Io> plus call(2, 3) ==> -1