SILVER HAIRED LISP の特徴
- Common Lispの入門書に書かれている程度のソースはそのまま動く事を目指している
- Clojure風の便利機能を少し取り入れている
- Java25で書かれている
- Javaのソースコードを吐くコンパイラを試作中
- Telnet接続も出来る(TeraTerm や PuTTY)
Common Lispの経験者が、少し追加で覚えるだけで、Java上のLispを扱えるようにする、またClojure風の便利機能を使える事を目標としています。
なぜJavaなのか
Javaで実装されたLispで有名なのはClojure, ABCL (Armed Bear Common Lisp), Kawaがあります。
Clojureは全くの独自文法でCommon Lispユーザーが覚え直すには、労力がかかりすぎます。
ABCLはCommon Lisp準拠ではありますが、開発年度が古く積極的に新機能を追加しようとはしていません。
KawaはSchemeの処理系です。
これらは、どれも開発を始めた年度が古く、最新のJavaの機能を使いこなしているとは言えません。
Common Lisp風の小さなLispをJava25で書いたらどうなるか興味があったので作り始めました。
SILVER HAIRED LISP(SHLISP) syntax
本Lispでは、common lispの入門書に出てくる程度のlispコードはそのまま動く事を目標にしています。
そのため、defmacro は以下のような書き方になります。
(defmacro my-quote (form) `(quote ,form))
しかし、 , は ` の中でしか使えません。
以下のような書き方は、OKです。
(defvar *a* 123)
`(quote ,*a*)
=> (quote 123)
しかし、以下のように、 , を `の外で使うと、エラーになります。
,*a*
comma not inside `
cl-user >>
123
java.lang.Integer
これは、,の所でエラーが発生したけれど、REPLはそのまま回っているので、次のaを読んで
123を表示した事になります。
JSON風の記述
話が変わりますが、以下はJSONの例です。
{
"id": 1,
"name": "山田 太郎",
"hobbies": ["読書", "プログラミング", "旅行"]
}
clojureは、 : を取り除けば 上記のような書き方が出来ます。
しかし私は、冒頭で示したように defmacroを書きたいため、 , を別の意味にする事をやめました。
本Lispでは、 , と、 : を省略する事で同様の事が出来ます。
{
"id" 1
"name" "山田 太郎"
"hobbies" ["読書" "プログラミング" "旅行"]
}
本Lispは多値もサポートしています。
SBCLで実行すると、以下のようになります。
* (values 1 1.2 "abc")
1
1.2
"abc"
本LispはJavaで書かれているため結果がどのJavaのクラスで返ってきたのか、分かった方が便利です。
そのため、SBCLで実行した事と同じ事を、本Lispで実行すると、以下のようになります。
cl-user >> (values 1 1.2 "abc")
1
java.lang.Integer
1.2d0
java.lang.Double
"abc"
java.lang.String
繰り返しになりますが、間違えて , を入力した場合、おかしな結果になりますので、注意してください。
cl-user >> [1, 2, 3]
comma not inside `
cl-user >>
2
java.lang.Integer
cl-user >>
comma not inside `
cl-user >>
3
java.lang.Integer
cl-user >>
Unmatched right parenthesis.
シンボルの大文字変換はしません
SBCLや大半のCommon Lispの処理系は、シンボルを大文字に変換してしまいます。
* '(a b c)
(A B C)
本Lispの場合、clojureのJava呼び出し記法のうち、基本的なものをサポートしています。
cl-user >> (defvar *sb* (new StringBuilder))
*sb*
io.github.shlisp.objects.Symbol
cl-user >> (.append *sb* "hello")
#<instance java.lang.StringBuilder>
java.lang.StringBuilder
cl-user >> (.toString *sb*)
"hello"
java.lang.String
ここで、問題になるのが、StringBuilder や、 toString といった大文字と小文字が混じった単語です。
Javaは大文字と小文字を区別する言語ですので、『大半のCommon Lispの処理系のようにシンボルを大文字に変換してしまう事』が問題になります。
本Lispでは、LispからJava呼び出しをサポートしたいため、小文字から大文字に変換するといった処理は、シンボルの : より右側について行わない仕様にしました。
cl-user >> (fboundp 'COMMON-LISP:car)
t
io.github.shlisp.objects.Symbol
cl-user >> (fboundp 'common-lisp:car)
t
io.github.shlisp.objects.Symbol
上記のように、 : より左にあるパッケージ名は大文字も小文字とも同じとみなします。
しかし : より右に書かれたシンボルは、大文字に変換する事はありません。