Posted 2018-08-27 17:23:54 GMT
色々な言語でCommon Lispのコードを書いてみたら、どうかなと思い試してみました。
だからなんなの、というような試みです。
コード例はお馴染みのfib
にします。
大元のCommon Lispです。
quote
を付ければデータになりますが、一応list
でリストを生成するものも書いてみます。
'(defun fib (n)
(if (< n 2)
n
(+ (fib (1- n))
(fib (- n 2)))))
(list 'defun
'fib
(list 'n)
(list 'if
(list '< 'n '2)
'n
(list '+
(list 'fib (list '1- 'n))
(list 'fib (list '- 'n 2)))))
当然ながらeval
すれば、コードとして実行できます。
まあ、RacketもCommon Lispもそのまんまですね。
1-
というシンボルは関数名としては不可だった気もします。
'(defun fib (n) (if (< n 2) n (+ (fib (1- n)) (fib (- n 2)))))
defun
等々の関数を定義すれば、そのまま動かせると思います。
PythonではCLのリストに相当するものは配列になるでしょう。
ASTやシンボルへのアクセスもできるようですが、とりあえず、面倒なのでシンボルは文字列としておきます。
['defun',
'fib',
['n'],
['if',
['<', 'n', 2],
'n',
['+', ['fib', ['1-', 'n']], ['fib', ['-', 'n', 2]]]]]
上のコードを動かすにはインタプリタを作成する感じなんでしょうか。
RubyもPythonと似た感じですが、シンボルがあるので使ってみました。
[:defun,
:fib,
[:n],
[:if, [:<, :n, 2], :n, [:+, [:fib, [:"1-", :n]], [:fib, [:-, :n, 2]]]]]
何故Erlangという気もしますが、Prologっぽいので試してみました。
やはりシンボルがあるので扱いが楽です。
[defun,fib,[n],['if',['<',n,2],n,['+',[fib,['1-',n]],[fib,['-',n,2]]]]]
Prologは、Lispと同様、基本のデータ型がリストです。Lispのシンボルはアトムに相当するでしょうか。
[defun,fib,[n],[if,[<,n,2],n,[+,[fib,[1-,n]],[fib,[-,n,2]]]]]
最近ブレイクしつつあるような気がするJuliaですが、シンボルがあるので、そこそこ素直に書けます。
[:defun, :fib, [:n], [:if, [:<, :n, 2], :n, [:+, [:fib, [Symbol("1-"), :n]], [:fib, [:-, :n, 2]]]]]
データをコードにする仕組みが割と身近に存在するようで、文字列をパーズしてExpr型というコードに変換することが可能です。
julia> xpr="function fib(n)
if n < 2
n
else
fib(n - 1) + fib(n - 2)
end
end"julia> Meta.parse(xpr)
:(function fib(n)
#= none:2 =#
if n < 2
#= none:3 =#
n
else
#= none:5 =#
fib(n - 1) + fib(n - 2)
end
end)
julia> Meta.show_sexpr(Meta.parse(xpr))
(:function, (:call, :fib, :n), (:block,
:(#= none:2 =#),
(:if, (:call, :<, :n, 2), (:block,
:(#= none:3 =#),
:n
), (:block,
:(#= none:5 =#),
(:call, :+, (:call, :fib, (:call, :-, :n, 1)), (:call, :fib, (:call, :-, :n, 2)))
))
))
コードをExpr
で直接記述することもできるようで、この辺りは、まんまLispの前置記法ですね。
Expr(:function, Expr(:call, :fib, :n),
Expr(:if, Expr(:call, :<, :n, 2),
:n,
Expr(:call, :+,
Expr(:call, :fib, Expr(:call, :-, :n, 1)),
Expr(:call, :fib, Expr(:call, :-, :n, 2)))))
ブログの内容が謎コンテンツでしたが、意外にもSmalltalk方面から反応を頂きました。
ありがとうございます🙇
「色々な言語でCommon Lispのコードを書いてみよう」https://t.co/AlI5lmFhvd をSqueak/Pharo Smalltalkで。
— sumim (@sumim) 2018年8月28日
#(defun fib (n) (if (< n 2) n (+ (fib (#'1-' n)) (fib (- n 2)))))
多くのSmalltalkの処理系ではリテラル配列表現の要素となるシンボルは#を省略できるので少しLispっぽく書けます。
シンボルがあるSmalltalkもかなりLispっぽく書けますね。しかも丸括弧。
Common Lispは、プログラムを文字のつづりというよりは、言語処理系のリスト型とシンボルで記述しますが、他の言語のデータ型を使ってCommon Lispのコードを書いてみたら面白いかなと思って試してみました。
当然ながら、やっぱり、Lisp、Prologあたりは、この辺りの処理はしやすいですね。
Juliaは数値計算にフォーカスしているものと思っていましたが、案外Lisp的なコード=データな文化も継承しているようで、なかなか面白いと思いました。
■
HTML generated by 3bmd in LispWorks 7.0.0