1.9.1 Maxima と LISP
MaximaはCommon Lispと呼ばれるLISPの一方言で記述されています. LISPは函数型と呼
ばれるプログラム言語で,プログラムは様々な函数を定義し,それらを組合せて行く作業とも言え ます.因みに,CやFORTRANは手続型と呼ばれます.
MaximaはこのLISPの上で動作する環境ですが,Maxima自体はPASCAL風の処理言語を持っ
ており,構文的にもLISPを意識する事は単純な利用では殆どありません.
但し,Maximaで酷いエラーを出すとLISPのデバッガに落ちる事があります. LISPのデバッガ からの抜け方は,Maximaを実装したLISPによって微妙に異なりますが,CLISPの場合は:qと入 力してみて下さい.するとMaximaに戻ります.
LISPの特徴は言語仕様が非常に柔軟な点です.LISPにはアトムと呼ばれる変数があり,それらを 空行で区切って小括弧()で括ったリストと呼ばれるデータが,最も基本的なデータとなります.こ のリストはリストのリストといったものも許容します.このアトムとリスト等で構成されたデータ をS式と呼びます.因に,LISPのプログラム自体もS式です.その為,LISPの函数でプログラムを操 作する事も容易に行えます.
その為,Maximaのプログラムでは足りない所をLISPで代用する事も多くあります. 又,Maxima からLISPを直接利用する事も可能です.この場合はMaximaのto lisp函数を利用します.Maxima で to lisp(); と入力すると, 裏方のLISPが表に出ます.これでLISPを使って遊べます.この状態 からMaximaに戻りたければ, (to-maxima)と入力します.すると通常のMaximaに戻ります.
(%i1) to_lisp();
type (to-maxima) to restart, ($quit) to quit Maxima.
Maxima> (setq $a ’1) 1
Maxima> (to-Maxima) returning to Maxima
(%o1) true
(%i2) a;
(%o2) 1
この例ではto lisp();でLISPに入って,アトム$aに1を割当てています. それから(to-maxima) でMaximaに戻っています.to lisp函数の返却値はtrueです.最後にa;を入力すると,LISPで$aに 割当てた値1が返却されます.これはMaximaでのアトムの内部表現では$aの様に先頭に$が付く からです.
この例で注目して頂きたい事は,Maximaで表示されているものとLISP側で見たものと様子が 違う事です.即ち,Maximaで扱うデータ,更には函数それ自体もLISP側では別の表記方法があり ます.このLISP側での表現を単純に内部表現と呼んでいます.この内部表現を通常の処理で気にす る事は殆どありませんが, 細かな処理を行う必要が出た時点で初めて意識する事になります.
尚,Maximaの函数名で先頭に?が付いているものが幾つか存在します.この様な函数は?を外した 部分はLISPの函数で,Maximaから裏のLISPで処理させて,その結果をMaxima側に持って来る 函数です.?は通常のLISP の函数にも適応可能で?を頭に付けた函数は,Maxima内部では?を外し て,LISPの函数として処理されます.この様にMaximaが介在する為,?を用いてLISPの函数を利 用する場合には,引数はMaximaで見えているものを設定します.
尚,?と函数の間に空行を入れるとMaximaのオンラインマニュアルを呼出そうとするので,注意 が必要です.
?と似た函数に:lisp函数があります. こちらは,直接LISPのS式をMaxima側から入力し,LISP に評価させた値を得る為の函数です.?演算子との違いは,?演算子では引数がLISPの函数で,その引
数はMaxima に準じたものとなりますが,:lispの場合はより一般的なLISPのS式となります. そ
の為,引数もMaximaの内部表現そのものとなります.
(%i26) a:x+y+z;
(%o26) z + y + x
(%i27) :lisp $a;
((MPLUS SIMP) $X $Y $Z) (%i27) :lisp (car $a) (MPLUS SIMP)
(%i27) ?car(a);
(%o27) ("+", simp)
上記の例では変数aにx+y+zを割当てていますが,$aが変数aの内部変数名となります. :lisp $a;
でこの変数に割当てた値を参照していますが, 返却値は内部表現そのものです.この様な変数の参 照は?では出来ません.
更に, :lisp (car $a);の値は内部表現そのものですが, ?car(a); の値はそれをMaximaで解釈し
た(”+”, simp)となっており,引数に$が付いていない事と:lispの結果に%oラベルが無い事に注目
して下さい.
この様に,?は入力と出力にMaximaが介在する為に,入出力をする度にMaximaの評価を受ける 事になりますが,:lispの場合は直接操作となります. :lispはMaximaで内部表現を確認する必要が ある場合に特に便利な函数です.
尚,MaximaはLISPで記述されている為,そのデータだけではなく,全てがLISPのS式で,LISP の函数で処理が可能となります.この事を利用してMaximaの機能を拡張する事が容易に行えます.
Maximaの函数をLISPから利用する場合,mfuncall函数を用います. この場合,引数はMaxima の函数名の頭に’$を付け,その後に引数を並べます.
MAXIMA> (mfuncall ’$diff ’$x ’$x 1) 1
この例では,変数xをdiff函数を使ってxで微分するものです.この様に,引数は全て内部表現に 対応したものでなければなりません. 従って,Maxima上で引数を割当ててある状態でなければ,使 い難いものです. 現実的には,Maxima函数の虫取りや動作の確認で用いる程度でしょう.