2004.7.11
全然更新してないのに、何かのご縁でせっかく訪れてくださったあなたにオマケ(・∀・)
下の内容からまったく進歩も進捗もないですが、なんだか Visual J# でもコンパイル通りました。
JAVA(TM) 信者のあなた、.NET 厨のキミ、Lisper のえらい人、石をなげないで....
とりあえず、VisualStudio2003 のプロジェクトフォルダまるごとここ↓においときますね。
コンパイル済みバイナリ(アセンブリ?)も含まれております(bin フォルダの下)。
miolisp.net20040711.zip
とりあえず、gui.lsp ,gui2.lsp, combinator.lspは動いてるみたいです。それしか確認してないです。
「Microsoft Visual J# .NET Version 1.1 再頒布可能パッケージ」
また、.NET Framework 自体のインストールも当然必要です。
「Microsoft
.NET Framework Version 1.1 再頒布可能パッケージ」
なお、上記の MS が提供するパッケージをインストールするにあたっては、それぞれの説明をよくお読みください。上記パッケージをインストールした結果、あなたの
PC の Windows の挙動が変になっても、
私は責任を負えません。あしからず。
はじめにお断りしておきますが、開発途上ということもあり、 きちんとしたモノには程遠いです。 なにかに流用、もしくはそのまま Lisp 処理系作成のレポートとして提出しよう などという学生の方はソースを見てがっかりしないようにしてくださいね(笑)
Mio Lisp は GNU GPL に基づいた配布ポリシーのフリーソフトウェアです。 配布条件に付いては、パッケージに附属のライセンス 文書 (和文)を御覧下さい。
このテキストを含むMio Lisp の最新版は こちら(jar archive, jar,unzip で解凍可)から入手できます。
動作確認環境は、インストールガイドを御覧下さい。
「開発を手伝ってもいい」という奇特な方、もしおられましたら御連絡おまちしております。
データ型 | ソースファイル中の 対応するクラス名 |
ソースファイル中の 親クラス名 |
備考(実装に関する情報) |
---|---|---|---|
シンボルアトム | SAtom | Atom | この型のアトムにのみ、値を束縛可能。 グローバル値および属性リスト(未実装)は、 このクラスのインスタンス内に保持される。 シンボルの唯一性を保持するために、全インスタンスへの参照を 保持するハッシュテーブルをクラス変数に持つ。 なお、この Lisp においてシンボルは全て大文字、あるいは大文字小文字の 混合で表記された場合でも、全て小文字として取り扱われる。 |
数値 | (Number) | --- | java.lang.Number 以下のクラスで流用する仕様に変更。
評価すると、値そのものを返す。
注意:リーダ (Sreader.java)は Double しか読めない。数値を読むと、java.lang.Double クラスのオブジェクトになる。(1/5) |
文字列 | (String) | --- | Java.lang.String を流用する仕様に変更。評価すると、値そのものを返す。 |
コンスセル | Cons | (Object) | -- |
マクロ関数 | Macro | (Object) | S 式で記述された関数(マクロ)。引数は評価しない |
ラムダ関数 | Lambda | Macro | S 式で記述された関数。引数を評価 |
Java ネイティブ関数 | NativeFunction | (Object) |
このクラスのインスタンスは、java.lang.reflect.Method のオブジェクト
(実体は LispFunction インターフェイスを継承するクラスの static メソッド)
を内部に保持する。 MioLisp の内部定義関数、拡張関数はすべてこのタイプ |
Java メソッド Java コンストラクタ |
(Method) (Constructor) |
--- | リストの car 部に Method,Constructor があるリストを評価すると、 cadr 部のオブジェクトに対し、invoke を使って残りのリストを 引数として Java メソッドを call する |
Java メソッド配列 | JavaMethod | (Object) |
リストの car 部にメソッド配列があるリストを評価すると、
cadr 部のオブジェクトに対し、invoke を使って、
残りのリストを引数として、配列の中から引数の形の
合致する Java メソッドを call する
(import) の拡張に伴って導入されたデータ型。 詳細は動的呼び出しのマップ を参照のこと。 |
(Java オブジェクト) | (上記以外の Object) | --- | Cons の car,cdr 部、およびシンボル束縛は 上記以外の Java オブジェクトへの参照も保持できる |
キャラクタ | 読み込み時の処理、変換など |
---|---|
'(クオート) | 'hogehoge を (quote hogehoge) に変換 |
`(バッククオート) | `hogehoge を (backquote hogehoge) に変換 |
,(コンマ) | ,hogehoge を (comma hogehoge) に変換
(backquote 内で、マクロ展開に使用) |
,@(コンマ+アット) | ,@hogehoge を (atmark hogehoge) に変換
(backquote 内で、マクロ展開に使用) |
.(ピリオド) | リスト中に現れた場合、直後の要素への参照をそのセルの cdr 部とする。 (a . (b c)) は (a b c) と等価 |
"(ダブルクオート) | ダブルクオートで区切られた部分を文字列型(java.lang.String)として処理 |
;(セミコロン) | 行末(EOL)までをコメントとみなす |
*この場合、呼ばれる側は常に static Object hogehoge(Environment e,Object o) となる。
*static メソッドの場合は第一引数は null を渡す
*static メソッドの場合は第一引数は null を渡す
cons. list. append. quote. backquote. lambda. macro. car. cdr. null. atom. setq. define. envaslist. env. if. eq. load. import. print. cond. reverse. equal. rplaca. rplacd. progn. prog1. mapcar.
基本関数の拡張は、上記 java ソースファイルに以下のシグネチャを持つ メソッドを追加することで行えます。
public static Object <FUNCNAME>(Environment e,Object o) ;
第一引数の e はローカル環境です。環境に対する操作を伴う関数を実装する場合、 直接 Environment クラスのメソッドを使用する必要があるかもしれませんが、 大抵は Eval.eval() の引数に使います。
第二引数の o は評価時点での cdr 部(評価の項 3-D を参照)の 先頭のセルへの参照がそのままの形(評価される前の形)で入っています。 通常の関数であれば、まず引数リストを評価する必要があります。
評価、およびリストの要素を順に取り出す操作などを簡単にするためのクラスとして、 Evalutil、 ListIter が用意されています。 使い方は、えっと、Primitive.javaを参考にしてください(笑)
但し、ListIter を使うと、引数の数を最後の引数を評価する段階で
チェックすることになるので、評価の最後で引数の個数が原因でエラーが
発生した場合、環境に影響がのこる可能性があります。
Macroクラス等の
S 式で定義された関数の評価では、引数の数のチェックを評価前に行っているので、
不整合がありますが、今のところ気にしないことにしています。
だれかもっと高速でエレガントな仕組みを作って僕に下さい(笑)。
(define myfunc (lambda (x y) ......))
第二引数の (lambda ...) が評価された時点で、 この部分は Lambda クラスのオブジェクトになります。
このように定義した関数呼出は
(myfunc arg1 arg2)
miolisp>(define mapcar (lambda (func list) (if (null list) nil (cons (func (car list)) (mapcar func (cdr list)))))) mapcar ---> 0 (ms). miolisp>(mapcar (lambda (x) (cons x x)) '(1 2 3)) ((1 . 1) (2 . 2) (3 . 3)) ---> 4 (ms).
Macro も Lambda と同様に関数オブジェクトですが、 引数が評価されない、定義式が2度(1回めはローカル引数リストに未評価の 引数が束縛された状態で評価し、2回目は元の環境で1回目の評価結果を)評価 される点が異なります。
また Lambda は (lambda ()) 評価時点(Lambda オブジェクト生成時点)のローカル 環境のコピーをオブジェクト内に保持しており、関数本体の評価時に それをひきずりますが、(closure とかいうものらしい(笑))が、 Macro はこれを行ないません。
え、なぜそうなってるか、ですか。えっとですね、実は僕も良く分かりません。 なんとなくそっちのほうが辻褄が合いそうな気がするからです。 辻褄が合わないことが分かれば、変えるかも知れません。
マクロ定義を見やすくするため、バッククオートとカンマ表記を サポートしています。これらの表記はリーダで S 式表現に展開され、実際の展開はPrimitive 内の backquote() (拡張関数形式) で行っています。
以下は Common Lisp 風の defun,defmacro を実現する Macro の例です。 参考にしてください。なんとなく分かると思います。
;; defun (define defun (macro (name arglist &rest body) `(define ,name (lambda ,arglist ,@body)))) ;; defmacro (define defmacro (macro (name arglist &rest body) `(define ,name (macro ,arglist ,@body))))
ありがちな(なんだそりゃ) &optional や &key は未実装です。
一応メッセージ部にそれらしい要因を入れていますが、 問題が起こった時点行き当たりばったりで throw しているため、 フォーマットも含め統一されているとは言いがたい状況です。
本来エラーの種類別に細分化するのが筋かと思いますが、
面倒そうなので手をつけていません。
ただ、一旦登録されてしまったシンボル(SAtom)は消えないので増える一方です。
さて、どうしましょうか ;-)
Java で記述されたクラスをより容易に利用するための仕組みとして、 import (実装は GetNative)、評価部を拡張しました。
おおまかには、(import "classname") で JDK 等一般のクラスも ロードできるようにし、それらのメソッドはフルクラス名とメソッド名を ピリオドで接続した印字名をもつシンボル(SAtom) に 大域値として束縛されます。
同じ名前で引数のパターン(シグネチャ)が違うメソッドを取り扱えるようにするため、 Java で記述された基本関数をロードする際に 行っていたような、 Method そのものを関数名のシンボルに束縛する方法ではなく、 新たに JavaMethod クラスを 作成し、その中に同名の Method を複数保持できるよう、Method の配列の形で 保持しています。
たとえば、(import "java.lang.String") を行うと、 java.lang.String クラスの toUpper メソッドは、 JavaMethod オブジェクトの形で java.lang.string.toupper という名前をもつ シンボルに束縛されます。
これで使用するメソッドごとに (native) を用いて生成する必要はなくなるものの、 呼び出し部の記述は同様に面倒です。
そこで、評価部を拡張し、
(<Object> "methodname" args....)
(object's.class.name.methodname <object> args....)
miolisp>("This is a String" "toUpperCase") "THIS IS A STRING" ---> 5 (ms).
この方法を用いた附属のサンプル(gui2.lsp)も 御覧下さい。
1999/1/5 以前のバージョンでは、メソッドの取得に Class.getDeclaredMethods() を
使っていたため、メソッドを Object まで遡って取得するというまぬけなことを
してましたが、Class.getMethods() を使う事に変更したため、この部分に関しての
記述をドキュメントから削除しました。(1999/1/5)
また、改めて見直すと、使わないものも含めて、全てのメソッドへの参照を
保持する必要性がないような気がします。そこで、
に出会った時にはじめてメソッドを検索する方式に変更し、Java Class の
呼出手順としての (import "....") を廃止する事を検討中です。(1999/1/5)
(object's.class.name.methodname <object> args....)
書籍名 | 著者/出版元 | 備考 |
---|---|---|
初めての人のための LISP |
竹内郁雄著
サイエンス社 ISBN4-7819-0454-8 |
マクロ、Closure のしくみなど、実装にあたって欲しい情報の ほとんどはこの本に書いてありました。 雑誌の連載をまとめた物のようで、対話形式になっており、 リファレンスとして使うには難がありますが、 買って損はないイチ押しの本です。 結構昔に買った本ですので、 まだ売ってるかどうかは分かりません(笑) |
JAVA IN A NUTSHELL, 2nd Edition |
David Flanagan著
O'Reilly & Associates, Inc. ISBN1-56592-262-X |
Sun から日本語版の HTML マニュアルが提供されているとはいえ、 JDK のメソッド定義の逆引き、定義クラス一覧など、Java でちょっとした おもちゃを作る際には手放せない 1 冊。JDK 1.0 対応の前版はもうすこし 小振りの大きさで持ち歩くのによかったのですが、肥大化しました。 (それとも、小型のも出てるんでしょうか?) |
Mio Lisp に関しての感想、御意見は、にしやま mio@mio.rim.or.jpまで。