#:g1: MIT FORMATの紹介

Posted 2014-11-25 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の330日目です。

MIT FORMATとはなにか

 MIT FORMATは、MIT系Lispでお馴染のFORMATです。

パッケージ情報

パッケージ名MIT FORMAT

インストール方法

 LispマシンのソースやMacLISPのソースからひっこ抜いてきて動かします。
Lispマシン版は、LMI LambdaのものをCommon Lispに移植してみたものがありますので興味があったらどうぞ。

試してみる

 MIT系Lispの機能で魔窟と化しているものの代表例として、FORMATとLOOPがあります。これら以外だとDEFSTRUCTとラムダリストもそうでしょうか。
拡張を繰り返して謎の機能を盛り込み、最終的にはユーザーが拡張できるようになることが多いようなのですが、Common Lispが出た頃には既に収束していたようです。
大別するとMacLISPのFORMATとLispマシンのFORMATがあるのですが、どちらも機能的には大体同じです。
MacLISP版の方は、MacLISP/NIL/Zetalispのスーパーセットのような方言でかつ、文芸的プログラミングのようにも書けて、コードからドキュメントも生成されるというLSBというフォーマットで書かれています(MIT/LCS/TM-200参照のこと)

 Common LispのFORMATと大体のところは同じですが、DEFFORMATでユーザーが拡張できます。
一文字の場合は、~文字 で呼び出せて、複数文字の場合は、~\名前~\ で呼び出せます。
Common Lispでも~//でユーザー定義の関数を利用可能なので、Common Lispでできないことといえば、一文字の指示子が定義できる位でしょうか(MacLISP/Zetalispではエスケープが\なので/と入れ替わっています。)

 defformatで漢数字を表示する指示子を作ってみると、

(knum (random (expt 10 63)))
;=>  "三百七十一那由他四千九百五十一阿僧祇二千七百九十八恒河沙三千九百七十六極九千三十九載四千三百七正二千七百六十九澗八千八百八十一溝六千九十一穣八千五百六十七𥝱八千五百九十五垓四千二百四十一京千八百九十九兆四千九百八億千六万四千九百十一"
;; のようなものが予め定義されているとする

(defun knum-format (arg params)
  (declare (ignore params))
  (princ (knum arg) *standard-output*))

(lambda.format:defformat(:one-arg) knum-format)

(lambda.format:format t "~D = ~:*~数" (random (expt 10 63)))
;>>  729257794194361409722610781525163841524812490803370431050961803 = 七百二十九那由他二千五百七十七阿僧祇九千四百十九恒河沙四千三百六十一極四千九十七載二千二百六十一正七百八十一澗五千二百五十一溝六千三百八十四穣千五百二十四𥝱八千百二十四垓九千八十京三千三百七十兆四千三百十億五千九十六万千八百三
;=>  NIL

のような感じでしょうか。上記では、ユーザーが登録できると説明しましたが、*FORMAT-CHAR-TABLE*に指示子の文字を登録しないといけないので、一文字の指示子は、あまりユーザーが気軽に定義するものでもないのかもしれません。
defformatでは、~{ ~}のような繰り返し構文も定義できるので、これを定義しだすとかなり奥が深いかもしれません。

 defformatによってCommon Lispにはないプリセットがいくつかあるので紹介してみます。

(lambda.format:format t "~\\time-interval\\" 100000)
;>>  1 day 3 hours 46 minutes 40 seconds
;=>  NIL

(lambda.format:format t "~\\datime\\") ;>> 12-Nov-14 22:04:55 ;=> NIL

(lambda.format:format t "~\\time\\" (get-universal-time)) ;>> 12-Nov-14 22:04:30 ;=> NIL

(lambda.format:format t "~\\date\\" (get-universal-time)) ;>> Wednesday the twelfth of November, 2014; 10:02:07 pm ;=> NIL

(lambda.format:print-list t "~2,'0D" '(1 2 3 4)) ;>> 01, 02, 03, 04 ;=> NIL

(lambda.format:format t "~\\scientific\\" (* 1.2 (expt 10.0 -18))) ;>> 1.20 atto ;=> NIL

(lambda.format:format t "~\\scientific\\" (* 1.2 (expt 10.0 12))) ;>> 1.20 tera ;=> NIL

(lambda.format:format t "~\\scientific\\" (* 1.2 (expt 10.0 18))) ;>> 1.20*10^18 ;=> NIL

等、主に時刻表示系の拡張が多いようです。~\scientific\は、あると便利かもしれません。

~Rの頑張り具合

 MIT系FORMATには色々な実装がありますが、~Rの表示についても色々です、Lispマシン版だと、

(format t 
        "~R"
        53999500948468952310038099781463571339047070077306365693157950031578865323656556470575617800343597469266163663053930729475284065797602507890543303778576751659589305608587610531708947533895013315667863040414361345468355481863098933946821494355280950711022187712940833316965953579893344816889296853809961893920288590813027274832826286947619604118250774207139185726707912013800939692113888334217321860037292466401359841909988633619607424903033450804126082814732707445124637525158238170968502713843469571111703598881772316107519263725449255479619898953254897560246329021003281382925172651714439764626563531074131156571665535676768755978740766873401181144256032811285441096311372679045330018428567938178094868712065068580809639275865131706462924775859365765458767892117014063125832876850531909154025650741916731357605935258947617751694792571197098071783553594056528313033244684266522404884784128003483709377045135811006490113848405279358750014669073521011548847837131136223674359357217325635332834429988293603397900589509479837107016653173146909465177952625778626216629083679921666803483394754450376941974550174091383204437716802171570061760417244518512843899701602964043259316720291129674329623222095297987389862598611240772884052719518970002304729523579043924577088361947008622544898239153515583379016768983297954121631081900889082400864067922600058400594238765010038489366358777002458031646082067722222514413839769452342632052290914556513716288379792729240853178303687025708955633480327380407923497850078420951985228579182612827147156878135218016259208631905768836986349361622245047674221778752695741210062306761661214307852665308621602864895728252916695112242072057480560958982341308100038716195984028347126604774936339276344081453742527548489965530976385763555878830918393648006130327327960704190904833212123903052891668786081836403824776774739850875709244292639039286939523104981546952953715780347934873229269429413881121903483764180865612725119566557443754191618555762081666047374746885983734614362337775745740375778738449658551507347449245742571619102174718114780803496920602156991309405209306051844513234344718816003897543309309554346752817036736575996706489202820650462415829202264497295289415112871468983090812832130317305226698442428490067416807537978549413114929045397194539604652830651471796026129295170532822597153883218867600018669161448985415894865487458662894655907371802544792611911196859473623714636886396579347590382034792368841023838815244989979251077104385311030453119874016830081042555655934964624991309367125628395577317651104735842449752179982674841263897030388895518361919869316899138079512261304365737790278071798129962236923346021371069026119976758928476946207645148585533271169588887008698168228540845488993201135317041879520393746627802502286733993852679366573642477866184470002897130179074050812975982271794837828584984428523206394416339396120267888799143183191074876414412012246672245565330593788479217065837148544042485924208932461014686265859689846010276942771331837221759)

は、

fifty-three times ten to the three thousandth power plus nine hundred ninety-nine times ten to the two thousand nine hundred ninety-seventh power plus five hundred times ten to the two thousand nine hundred ninety-fourth power plus
....
eight hundred thirty-seven million two hundred twenty-one thousand seven hundred fifty-nine

のように表示されるため、上限は特にないようです。
ちなみに、~Rで随分と頑張っているのは、CMUCLのFORMATで、上記の例だと、

fifty-three novenonagintanongentillion nine hundred ninety-nine octononagintanongentillion five hundred septenonagintanongentillion nine hundred forty-eight senonagintanongentillion four hundred sixty-eight quinquanonagintanongentillion nine hundred fifty-two quattuornonagintanongentillion three hundred ten trenonagintanongentillion thirty-eight duononagintanongentillion ninety-nine unnonagintanongentillion seven hundred eighty-one nonagintanongentillion four hundred sixty-three novemoctogintanongentillion five hundred seventy-one octooctogintanongentillion three hundred thirty-nine septemoctogintanongentillion forty-seven sexoctogintanongentillion seventy quinquaoctogintanongentillion seventy-seven quattuoroctogintanongentillion three hundred six tresoctogintanongentillion three hundred sixty-five duooctogi
....
thirty-one billion eight hundred thirty-seven million two hundred twenty-one thousand seven hundred fifty-nine

と表示されます。10の3002乗のone hundred novenonagintanongentillionまでサポートしている様子。10の3003乗からはエラーになります。

まとめ

 今回は、MIT FORMATを紹介してみました。
これが1980年前後のMITの魔拡張機能だ!と思って紹介するつもりでしたが、FORMATは割とCommon Lisp版にも機能が取り込まれていました。
Common Lispのformatの~//で便利に使える関数は、それほど流通していないようなので便利な物が流通すると良いですね。

comments powered by Disqus