`(Hello ,world)

ツッコミ、添削大歓迎です。いろいろ教えてください。

2009-04-22

Lisp-85での関数定義

関数定義はDEFUNで行います。

(DEFUN 関数の種類 関数名 引数リスト 関数本体)

関数の種類は、引数が関数に渡ってくるときにあらかじめ引数を評価するかしないか、引数が固定長か可変長か、あとマクロ MACRO の5種類あります。

引数の数\評価するしない
固定長EXPRNEXPR
可変長LEXPRFEXPR
EXPR: 固定長の関数

EXPRの場合は定義時の「関数の種類」の指定を省略することができます:

>(DEFUN SQ (X) (TIMES X X))
SQ
>(SQ 111)
12321
LEXPR: 可変長の関数

仮引数には引数の個数が入ってくるので、それをARG関数で取り出します(1オリジン):

>(DEFUN LEXPR PRINT-ARGS N
   (PROG (I)
     (SETQ I 0)
    LOOP
     (COND ((LESSP I N)
            (PRINT (ARG (SETQ I (ADD1 I))))
            (GO LOOP)))))
PRINT-ARGS
>(PRINT-ARGS 123 'ABC "Hello")
123
ABC
"Hello"
NIL
NEXPR: 固定長の非評価関数

引数が評価されずに渡ってくるという点以外はEXPRと同じです:

>(DEFUN NEXPR QCONS (X Y) (CONS X Y))
QCONS
>(QCONS hello world)
(hello . world)
FEXPR: 可変長の非評価関数

同じ可変長のLEXPRの場合とは違い、引数がリストとして仮引数に渡されます:

>(DEFUN FEXPR QLIST X X)
QLIST
>(QLIST this is a pen)
(this is a pen)
MACRO: マクロ

引数がリストとして仮引数に渡され、返した値が評価されて最終的な値になります。FEXPRと違い仮引数は1つだけど括弧でくくる必要があり、仮引数にはマクロ名もついた状態で渡ってきます:

>(DEFUN MACRO QMACRO (X) (LIST 'QUOTE X))
QMACRO
>(QMACRO this is a pen)
(QMACRO this is a pen)

これらをふまえて、IF マクロを定義してみます。Lisp-85インタプリタにはバッククォートがないので、自分でリストを作る必要があります。else式があるかないかで分岐させて以下の具合になります:

(DEFUN MACRO IF (X)
  (COND ((CDDDR X)
         (LIST 'COND (LIST (CADR X) (CADDR X))
               (LIST 'T (CAR (CDDDR X)))))
        (T
         (LIST 'COND (LIST (CADR X) (CADDR X))))))
感想
  • カオスすぐる…。こういうところから始めたら絶対Lisp嫌いになると思う。
  • NEXPRとFEXPRは存在価値あるのかな?
  • 組み込み関数も同様にSUBR, LSUBR, NSUBR, FSUBR とあるそうだけど、L, N, F はなんの略だろう?

通りすがり通りすがり2009/04/24 20:11FEXPRを使ってIFを書くと少しすっきりしますよ。
(DEFUN FEXPR IF X
(COND ((EVAL (CAR X)) (EVAL (CADR X)))
((CADDR X) (EVAL (CADDR X)))))
それにしても懐かしいなぁ。
一応Oh!MZはあることにはあるのですが
ダンボール箱から目的のぶつを探すのが大変だったりします(笑)

mokehehemokehehe2009/04/25 14:01そうそう、サンプルとしてIFをFEXPRで作るのが載ってるんですよね。
インタプリタだと、マクロで変形したリストを作ってから再評価するよりFEXPRとかで受け取って必要な部分だけEVALの方が速い、とかの理由ですかね。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20090422

2009-04-20

「S-OS」エミュを作って「Lisp-85」を動かす

その昔「Oh! mz」というパソコン雑誌があって、清く正しいシャープユーザだった俺のとうちゃんは毎月買っていた。1985年にその紙面上でLisp-85という処理系が発表された。

当時は言語オタクじゃなかったしマシンも非力だったからZ80のアセンブラにしか興味がなかったので打ち込んだり動かしたりしたことはなくて雑誌のバックナンバーも処分してしまったんだけど、どうしても動かしたくなったので国会図書館まで行って記事をサルベージしてきた。

Lisp-85はS-OSという、これまたOh! mz紙上で発表された共通OS上で動くものとなっている。本来なら8ビットコンピュータのエミュレータを使って動かせばいいんだけどその環境を整えるのがメンドイので、fMSXで使われてるZ80エミュレータを使って、S-OSのシステムコールを真似て動かしてみた。

f:id:mokehehe:20090422160633p:image

ビルド方法

ソースはgithubに置いた。Lisp-85に限らずS-OSのアプリを動くようにしたいと思ってる。

それにfMSXZ80エミュレータのソースを持ってきてmakeすれば実行ファイルが出来上がる。

実行方法

できた実行ファイルに大石さんのところにおいてあるLisp-85.objを食わせる:

> ./s-os.exe Lisp-85.obj
処理系
  • 大石さんいわく、「MacLispを参考に作られた、CP/M用のフルセットLispに匹敵するLispインタプリタ」
  • 組み込み関数はすべて大文字
  • エラーから復帰するには (TOPLEVEL)
  • 四則演算は PLUS, DIFFERENCE, TIMES, QUOTIENT
  • IFはなくてCOND
  • 例1:ハノイの塔
(DEFUN HANOI (N A B C)
  (COND ((ZEROP N) NIL)
        (T (APPEND (HANOI (SUB1 N) A B C)
                   (CONS (LIST 'MOVE N 'FROM A 'TO C)
                         (HANOI (SUB1 N) B A C))))))
(PP (HANOI 3 'A 'B 'C))

あとまあおいおい説明します。

g000001g0000012009/04/20 22:08これは濃いですね!
国会図書館からサルベージとか凄すぎますw

mokehehemokehehe2009/04/21 07:45Lisp-85はMacLispの系譜とのことで、g000001さんにも喜んでもらえることと思います!

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20090420