#:g1

Common Lispのお宅拝見: LispWorks篇

Posted 2017-05-07 15:23:16 GMT

Common Lispを利用する上で普段何気無く利用しているcl-userだが、実は処理系毎にユーティリティの充実度等が結構違っている。
そこで、ホームパッケージであるcl-userパッケージを処理系毎に観察してみよう。

今回は、LispWorks 7.0 を眺める。
LispWorksは様々なプラットフォームで稼動するのでプラットフォーム依存な所はあるのだが、cl-userのが取り込んでいるパッケージは下記の通りで、LISPWORKS(lw)とHARLEQUIN-COMMON-LISP(hcl)を取り込んでいる。

(package-use-list :cl-user)

→ (#<The COMMON-LISP package, 2/4 internal, 978/1024 external> #<The HARLEQUIN-COMMON-LISP package, 0/8 internal, 353/512 external> #<The LISPWORKS package, 0/4 internal, 224/256 external>)

defpackageした際に:useを省略するとデフォルトのパッケージが取り込まれるが、上記3つが:useされるのがLispWorksの標準。

ちなみに、Harlequin Common LispというのはLispWorksを元々作っていた会社がHarlequinということに由来する。
Harlequin社は、〜Worksという名前で製品を作ることが多かったが、元々は、Harlequin CLを中心とした開発環境がLispWorksということだったらしい。

lwパッケージとhclパッケージの使い分けが判然としないが、hclパッケージの方がCLtL1時代からのユーティリティが多い気がするが、lwhclを合せて600近くのシンボルがあるので、結構ごちゃごちゃしているなあという印象はある。

これらユーティリティで有名なところでは、when-letif-letwith-unique-namesrebindingsplit-sequence辺りだろうか。
with-unique-namesは、with-gensymrebindingonce-onlyとして知られているマクロだが結構見掛けることは多いかと思う。
split-sequenceはQuicklispにもあるユーティリティと同名だが、LispWorksがオリジナルなのかもしれない(とはいえ微妙に仕様が違う)

また、オリジナルのloopにあったユーザー定義の構文がデフォルトで使えるので、

(define-loop-macro for)
(define-loop-macro repeat)
(define-loop-macro with)

(for i :from 0 :repeat 10 :collect i) ;=> (0 1 2 3 4 5 6 7 8 9)

こんなこともできるし、さらにユーザーがデータ型の処理方法を任意に定義することもできる(defloop等)

また、非常にどうでも良い所ではあるが、ユーティリティに定義されていることが多いtruefalseも用意されている。

(mapcar #'true (repeat 20 :for i :from 1 :collect i))
;=> (t t t t t t t t t t t t t t t t t t t t) 
(mapcar #'false (repeat 10 :for i :from 1 :collect i))
;=> (nil nil nil nil nil nil nil nil nil nil) 

Common Lispにはconstantlyがあるので不要に思えるのだが、用意している処理系は結構ある。

結び

以前から、処理系ごとにcl-userを比較してみていたが、これまで資料は貯めていたものの何故か書いたことがなかった。
今後、暇潰しに他の処理系についても書いてみるつもりである。


HTML generated by 3bmd in LispWorks 7.0.0

Lisp本積読解消: 素数夜曲―女王陛下のLISP: B.5.3 構文の拡張

Posted 2017-05-07 07:04:39 GMT

今回は、素数夜曲―女王陛下のLISPのマクロの箇所を読む。
本書は、数学の本なのだが、Lisp(Scheme)についての内容が半分を越えるということで知られているらしい。
マクロの解説もあったので眺めてみた。

B.5.3 構文の拡張

著者は、例外をできるだけ少なくなるようにプリミティブまで分解した結果、利用者がプリミティブを組み合せて目的の物を作るというScheme流のスタイルが生れてくるという解釈をしている。
関数と残りの例外である特殊形式まで分解した結果、それらを組み合せるというマクロが生きてくる、という解釈。
綺麗な解釈だとは思うが、正直考え過ぎかなと思った。
ただ、Lispマクロは特殊形式を減らそうというのが出自であったので、著者の考えと順番は逆にはなるが、プリミティブに分解する方向では同じかもしれない。

さて、マクロの解説だが、構文の拡張の例として、ifthenelseのキーワードをつける例を紹介。syntax-rulesを用いるので特にややこしい説明はない。
次に、notandが合体したnandincdecを作る。

最後に、delayed consの構文を定義するということで、s-conss-cars-cdrを定義し、delayforceを隠蔽してみせる。
関数でも定義可能なものになっているので、何故マクロを使ったのかは分からないが、この章は構文の拡張がお題だからだろう。

結び

数学の本なのに一応Schemeマクロの解説までしてあるというのは凄いと思う。


HTML generated by 3bmd in LispWorks 7.0.0

CL-Cleanup、CL-Compilerメーリングリストをまとめてみた

Posted 2017-05-04 07:45:45 GMT

なんとなくsaildart.orgからCL-Cleanup、CL-Compilerメーリングリストのファイルを抜き出して纏めてみた。
メーリングリストの期間や、元データ等の詳細は、ml.cddddr.orgのフロントページに記載してある。

CL-Cleanupの方は、HyperSpecの付録として配布されているので割合に目にしたことがあるかもしれない。
あのイシューを議論していたのが、CL-Cleanupだったらしい。

CL-Cleanupを眺めて興味を持ったらHyperSpecのまとめを参照してみるというのも良いかもしれない。

どうも:1をどういう風に解釈したら良いかも議論して決めたことだったらしく感心してしまう。

CL-Compilerの方も眺めてみると興味深いことが多いというか、Common Lispの理解が深まりそうな気がする。


HTML generated by 3bmd in LispWorks 7.0.0

Common Lispのeltとnthの違い

Posted 2017-05-02 04:41:51 GMT

Common Lispのeltsequence全般に使えるが、リストで使う場合には、nthとは微妙に挙動が違う。

(let ((u '(0 1 2 3 4 5 6 7 8 9) ))
  (list (nth 100 u)
        (multiple-value-list (ignore-errors (elt u 100)))))
;=> (nil (nil #<conditions:index-out-of-range 40202E27E3>)) 

eltは上記のようにシークエンスの範囲外ではエラーとなるが、インデックスはvalid array indexであることと定められているのであった。

対してnthはインデックスは、a non-negative integerである。 範囲外ではnilを返す。

ちなみに似たようなものには、endpnullの関係がある。

(let ((u '(a . d)))
  (list (null (cdr u))
        (multiple-value-list (ignore-errors (endp (cdr u))))))
;=> (nil (nil #<type-error 402015AD53>)) 

結び

どこかで書いたことがある気がしたが、どこに書いたのか思い出せないのでまた書いてしまった。
チェックも厳しいのでeltで済むなら、elt書いた方が良いだろう。
ちなみに、eltで書いても最適化すれば大抵の場合nth同等になる。


HTML generated by 3bmd in LispWorks 7.0.0

Seriesの色々

Posted 2017-04-27 16:36:10 GMT

久々にSeriesのブログ記事を見掛けたが、ブログ中にこんな疑問があった

``上のコード、実行するたびに以下のようなwarningが出るんですよね。なんとかならないものか。''

これは大抵の場合、seriesのパイプラインに載ってないのが理由である。
Seriesでは最適なコードを出すには色々な制約があり、色々繁雑な作法があるのだった。

この流れて行くと元のコードをSeries的に最適化して、やったね!という締めになりそうだが、このコードを最適化するのはどうも大変っぽいので別の書き方をすることにした。

とりあえずは、パッケージの定義から

(defpackage :Z
  (:use :cl :series))

(in-package :Z)

(series::install :implicit-map T)

まず、Seriesを最適化するにはseries::installの実行が大切である。
リーダーマクロが導入されるに留まらず、letdefunfuncallが改造されてしまう。この辺りは好き嫌いが分かれるだろう。ちなみに筆者はあまり好きではない。

implicit-mapはデフォルトではnilだが筆者はこの怪しい機能が好きなのでTにしたい。

implicit-mapTだとこのように書ける

(let ((e (scan-range))
      (s (scan "響け!ユーフォニアム")))
  (collect (list e s)))
;=> ((0 #\響)
;   (1 #\け)
;   (2 #\!)
;   (3 #\ユ)
;   (4 #\ー)
;   (5 #\フ)
;   (6 #\ォ)
;   (7 #\ニ)
;   (8 #\ア)
;   (9 #\ム)) 

ぱっと見普通だが良く考えると色々変なことになっている。

恐らくこの機能は、seriesの前身のLetSの構文を実現するものなのではないかなと考えているが実際はどうなのだろう。

閑話休題。それで、とりあえず、clojureのcycleみたいなユーティリティを考えてみる。

(defun cycle (seq)
  (declare (optimizable-series-function 1)) 
  (let ((len (length seq)))
    (scan-fn '(values character fixnum) 
             (lambda () (values (elt seq 0) 0))
             (lambda (c prv &aux (cur (1+ prv))) 
               (declare (ignore c))
               (values (elt seq (mod cur len)) cur))
             (constantly nil))))

(subseries (cycle "響け!ユーフォニアム") 0 20) ;=> #Z(#\響 #\け #\! #\ユ #\ー #\フ #\ォ #\ニ #\ア #\ム #\響 #\け #\! #\ユ #\ー #\フ #\ォ #\ニ #\ア #\ム)

(declare (optimizable-series-function 1))が肝だが、defunもSeriesの独自定義のものに差し換えられており、後々ループに組み直す為に定義時に中身が分解されて格納されたりしている。
defunマクロを展開すると通常のcl:defunとは似ても似つかない内容になっているので眺めてみよう。

それで、本体だが、一文字ずつずらしながら改行されているということは、該当の場所の文字を改行に置き換えてしまえば良いのではないかということで、このように書いた

(defun 響け!ユーフォニアム ()
  (let* ((str "響け!ユーフォニアム")
         (len (length str)))
    (collect-ignore
     (#2M(lambda (c i)
           (write-char (if (= len (mod i (1+ len))) #\Newline c)))
         (cycle str)
         (scan-range :length (* len (+ 2 len)))))))

なお、implicit-mapが有効なので、#2Mは取ってしまえるので、こうなる

(defun 響け!ユーフォニアム ()
  (let* ((str "響け!ユーフォニアム")
         (len (length str)))
    (collect-ignore
     ((lambda (c i)
        (write-char (if (= len (mod i (1+ len))) #\Newline c)))
      (cycle str)
      (scan-range :length (* len (+ 2 len)))))))

さらにlambdaletに纏めることが可能。

(defun 響け!ユーフォニアム ()
  (let* ((str "響け!ユーフォニアム")
         (len (length str))
         (c (cycle str))
         (i (scan-range :length (* len (+ 2 len)))))
    (collect-ignore
     (write-char (if (= len (mod i (1+ len))) #\Newline c)))))

(響け!ユーフォニアム) ;>> 響け!ユーフォニアム ;>> け!ユーフォニアム響 ;>> !ユーフォニアム響け ;>> ユーフォニアム響け! ;>> ーフォニアム響け!ユ ;>> フォニアム響け!ユー ;>> ォニアム響け!ユーフ ;>> ニアム響け!ユーフォ ;>> アム響け!ユーフォニ ;>> ム響け!ユーフォニア ;>> 響け!ユーフォニアム ;=> nil

そして、この定義をマクロ展開すると、こんな恐しいことになっている (実行可能なように#:は取ってある)

(defun 響け!ユーフォニアム ()
  (cl:let* ((str "響け!ユーフォニアム"))
    (cl:let (len)
      (setq len (length str))
      (cl:let (out-137857)
        (setq out-137857 (* len (+ 2 len)))
        (cl:let (out-137847)
          (setq out-137847 (length str))
          (cl:let (out-137846 out-137845)
            (setq out-137846
                  #'(lambda (c prv &aux (cur (1+ prv)))
                      (declare (ignore c))
                      (values (elt str (mod cur out-137847)) cur)))
            (setq out-137845 (constantly nil))
            (cl:let (state-137844
                     (state-137843 0)
                     items-137848
                     (items-137842 0)
                     (i (coerce (- 0 1) 'number))
                     (counter-137854 out-137857))
              (declare (type fixnum state-137843)
                       (type fixnum items-137842)
                       (type number i)
                       (type fixnum counter-137854))
              (locally
                (declare (type character state-137844)
                         (type character items-137848))
                (values (cl:let* ()
                          (cl:multiple-value-bind (|Store-Var-137865|
                                                   |Store-Var-137866|)
                                               ((lambda () (values (elt str 0) 0)))
                            (cl:let* ()
                              (values (setq state-137844 |Store-Var-137865|)
                                      (setq state-137843 |Store-Var-137866|))))))
                (tagbody
                 ll-137864 (if (cl:funcall out-137845
                                           state-137844
                                           state-137843)
                               (go series::end)
                               nil)
                 (setq items-137848 state-137844
                       items-137842 state-137843)
                 (values (cl:let* ()
                           (cl:multiple-value-bind (|Store-Var-137867|
                                                    |Store-Var-137868|)
                                                (cl:funcall out-137846
                                                            state-137844
                                                            state-137843)
                             (cl:let* ()
                               (values (setq state-137844
                                             |Store-Var-137867|)
                                       (setq state-137843
                                             |Store-Var-137868|))))))
                 (setq i (+ i (coerce 1 'number)))
                 (if (not (plusp counter-137854)) (go series::end) nil)
                 (cl:let* ()
                   (cl:let* ()
                     (cl:let ((|Store-Var-137869|
                               (- counter-137854 1)))
                       (setq counter-137854 |Store-Var-137869|))))
                 (write-char (if (= len (mod i (1+ len)))
                                 #\Newline
                                 items-137848))
                 (go ll-137864)
                 series::end)
                nil))))))))

おわかり頂けただろうか……別々に定義した関数の中身が合体していることが分かると思う。

結び

筆者も以前はSeriesを好んで利用していたが最近は面倒なのでSeriesを使って書いたりしていない。

どうもSeriesを使って何か書いていると、Seriesが上手く最適化されないなーなどとチューニングの為に横道に逸れてしまうことが多いのだった。

Seriesだと繰り返しを関数の組み合わせのように書けるが、実際の所はまさしく黒魔術なマクロでループに式を変形していて、Seriesの作法を知らないとビシッとループには展開されない。
綺麗にループに展開されない場合は、非効率なコードが出てしまうが、冒頭の警告の話は、このような背景による。

この辺りはコンパイラがすべきことなんじゃないかなあと思ってしまうが、マクロの可能性の一つではあるのかもしれない。

とりあえず、Seriesの標準のユーティリティにあまり使い易いものはないが、Clojureあたりを参考にユーティリティを作る所から始めれば、Seriesも快適に使えたりするのかもしれない。


HTML generated by 3bmd in LispWorks 7.0.0

教養としてのCommon Lisp

Posted 2017-04-26 17:35:08 GMT

Common Lispを学ぶにも色々な動機があるが、言語オタクがCommon Lispを学ぶ上で、他の言語とはちょっと毛色が違ったアピールポイントを筆者なりに考えてみた(暇だったので)。

30年前にはかなり尖っていたかもしれない仕様だが、今となってはかなり他の言語に機能がキャッチアップされているCommon Lisp。
まず、筆者的には、対話環境がすなわち言語処理系ということがCommon Lispの特長かなと思っているのでその辺りを推したい。
evalが発展して対話環境ともなり、コンパイラとも連携しているということが醍醐味なのかなと思っている。
なお突き詰めれば、二村射影とか部分評価とかその辺りに関連していくのかもしれないが筆者は良く知らない。

それと、良く言われるProgrammable Programming Languageということ。
Lispを書くようになると当たり前に感じられることだがLispの特長だろう。
Common Lispを書けば、Programmable Programming Languageを実現するための道具立ても豊富であることも分かると思う。

などなど考えて学習トピックを並べてみた

  • 始めに対話環境があり、それがコンパイラを含むようになったという流れ

    • ランタイムにコンパイラを含め全ての機能が含まれているということ(実行時コンパイルなど)
    • インタプリタ動作とコンパイラ動作に矛盾がない仕様とその実現努力
  • Code as data、programmable programming languageということ

    • リスト処理/コード処理
    • ユーザーが目的に応じて処理系をカスタマイズするということ

      • ユーザー拡張の例:フックできる場所の例とフックを実現する機構
      • evalを直接拡張していた時代のおさらい
      • リード時、コンパイル時、ロード時評価
      • リーダーマクロ、マクロ、マクロ展開時のフック、MOP(オブジェクトシステムの動作の規約に則ったカスタマイズ)、アドバイス機構
  • 言語の策定プロセス:取捨選択のプロセス

    • 過去の処理系/Lisp文化との互換性の取捨選択
    • Lisp専用マシンから汎用マシンをメインのターゲットにしたということ
  • より発展的な処理系との比較: Racketなど (素朴 vs 先進的機能)

    • Lisp-1 vs Lisp-2
    • サブセット的な規格との比較: Common Lisp vs ISLISP (Common Lispでは何が繁雑だと考えられたか)

なお、対話環境については、コードを書いて対話的にデバッグしてみないと分からないのでコードを書くしかないかもしれない。
マクロのデバッグが困難であると先入観を持っている人は多いが、素朴な仕組みなので所詮リスト処理のデバッグが殆どである。
マクロについてはScheme/Racketしか触っていないとちょっと違った印象を持つのかもしれない。

とりあえず、Lisp族を語るならばCommon Lispを知っていることは必須だろうと思う。
何故なら多数の方言があるLispの中で良くも悪くも一つの基準となってしまったのがCommon Lispで、Schemeが反発しつつもCommon Lispの機能を取り込んだりアレンジしたりしているし、Clojureもしかり、Emacs LispはCommon Lispの前身から枝分かれしているが、rmsのCommon Lispへの反発があったり。

なんだかんだでネタ元を知るのが理解の近道だと思うし、まさに教養としてCommon Lispを押えておいた方が言語オタクの井戸端会議は盛り上がると思う。


HTML generated by 3bmd in LispWorks 7.0.0

Zetalispのlambda-macro

Posted 2017-04-23 16:30:51 GMT

今日は一日LMI Lambdaのエミュレータを触っていたが、そういえば、Zetalispにはlambda-macroというものがあることを思い出した。
(ちなみに、LMIのZetalispは、ZetaLISP-Plusらしい……)

lambda-macroの使い所だが、Common Lispでarcのfnを再現することを考えてみよう。
arcのfnは大体Common Lispのlambdaだが、fnには引数の解構destructuring機能がある。

Common Lispのマクロで書くなら、

(defmacro fn ((&rest args) &body body)
  (let ((a (gensym)))
    `(lambda (&rest ,a)
       (destructuring-bind (,@args) ,a
         ,@body))))

こんな感じで、こうなる

(mapcar (fn ((a . d)) (list a d))
        '((0 1 2 3) (1 1 2 3) (2 1 2 3)))
;=> ((0 (1 2 3)) (1 (1 2 3)) (2 (1 2 3))) 

しかしそれで元のlambdaのように

((fn ((a . d)) (list a d)) '(0 1 2 3))

と書けるかというと、こうは書けない。

ここがCommon Lispでは微妙にもどかしい所だが、Zetalispでは、lambda-macroを定義してやれば思ったように書ける。

(deflambda-macro fn ((&rest args) &body body)
  (let ((a (gensym)))
    `(lambda (&rest ,a)
       (destructuring-bind (,@args) ,a
         ,@body))))

((fn ((a . d)) (list a d)) '(0 1 2 3))
;=> (0 (1 2 3)) 

さらに、deffunctionという引数の取り方をカスタマイズした関数を定義する構文が用意されていて、上記のfnを下敷にする関数は、

(deffunction a.d fn ((a . d))
  (list a d))

(mapcar #'a.d '((0 1 2 3) (1 1 2 3) (2 1 2 3)))
;=> ((0 (1 2 3)) (1 (1 2 3)) (2 (1 2 3)))

と書ける。

結び

Lispマシンのマニュアルの解説箇所はこちら

まあ、Lisp-1 ならこういうものは素直に書けるのだが。


HTML generated by 3bmd in LispWorks 7.0.0

LMI Lambdaのエミュレータ:LambdaDelta 公開!

Posted 2017-04-23 05:55:47 GMT

最近、LispマシンのメーリングリストでLMI Lambdaのエミュレータが完成間近であることがアナウンスされていたが、今日LambdaDelta 0.98.1が公開された。
やった!、思いの外公開されるのが早かった。

早速起動したい所だが、ROMや、テープイメージ等を準備する必要がある。

必要なものを取得しつつのビルド手順は下記の通りとなった。
ホストOSは、Debian GNU/Linux 64bit

### LambdaDelta本体の準備

wget https://github.com/dseagrav/ld/releases/download/0.98.1/ld-0.98.1.tar.gz tar xvf ld-0.98.1.tar.gz cd ld-0.98.1 ./configure --without-SDL1 make

### ROMの準備

cd roms wget http://bitsavers.trailing-edge.com/pdf/lmi/firmware/SDU_15165-0003.ZIP unzip SDU_15165-0003.ZIP wget http://bitsavers.trailing-edge.com/pdf/lmi/firmware/VC_MEM.ZIP unzip VC_MEM.ZIP http://bitsavers.trailing-edge.com/pdf/lmi/firmware/Memory/2243902_OF_27S291.BIN

ln -s VC_MEM/U43_2516_2242843-0001_0856TI200038.BIN VCMEM.ROM ln -s 2243902_OF_27S291.BIN MEM.ROM ln -s SDU_15165-0003/combined.BIN SDU.ROM cd ..

### インストールテープの準備

cd tapes wget http://bitsavers.trailing-edge.com/bits/LMI/lambda/00_install.tap wget http://bitsavers.trailing-edge.com/bits/LMI/lambda/02_system.tap cd ..

### ディスクの準備

fallocate -l 1gib disks/disk.img

### 初期化ファイルの準備

echo "sdu_switch 0" > ld.conf

あとは大体READMEに書いている通りに進めばセットアップは完了する

インストール時のはまりどころ

一番最初は、ld.confをどう書くのか最初は良く分からないのでデフォルト値を利用することになる。
はまりそうなデフォルト値は、ディスクのdisks/disk.img位かなと思う。

また、イーサネットデバイスを利用するのにroot権限が必要だが、

sudo modprobe tun 
sudo tunctl -t ldtap -u ユーザー

等とするか、root権限で実行することになると思う。 Xの画面が開かない時は.Xauthorityをrootのホームディレクトリにコピーする等適当に凌げば良いかもしれない。

170423130139

起動できたら、とりあえず、ユーザーのホームディレクトリでも作成してみる。

(fs:create-directory "mc")

そしてログイン(特に何も起きないが……)

(login 'mc)

初期化ファイルは、ユーザーディレクトリのlispm.initらしい(CADRと同じ)

170423130315

バックアップテープからのリストア

F12でテープを02_system.tapに切り替えて、System B(F1を押してからB)でバックアップユーティリティを起動。 中程のメニューのModesからRETRIVEを選んで、上のCommandsメニューからRESTORE-FILESを選択すると、読み込みと展開が始まる。結構長い。

lmi-lambda-restore

結び

とりあえず速報という感じでまとめてみた。
ホストとのファイル共有や、ネットワーク周りがまだ良く分からないが、ホストとファイルをやりとりできるようになると非常に捗るので方法を探りたい。

いやー、LambdaDeltaの今後の進展が楽しみだ!


HTML generated by 3bmd in LispWorks 7.0.0

Lisp本積読解消: Notes on the Programming Language LISP: The Macro Facility

Posted 2017-04-20 15:22:38 GMT

今回は、最近bitsaversにアップされた、Bernard Greenberg氏が1976-78年に書いたLispの入門の手引きNotes on the Programming Language LISPのマクロの章を読む。

Bernerd Greenberg(BSG)氏といえば、Multics Emacsの作者として有名だが、Lispハッカーとしても有名。
そんなBSG氏がMITの学生向けに書いた手引きらしい。
書かれた時期は、BSG氏がまさにMultics Emacsを開発していた頃にあたる。

The Macro Facility

まず、Maclispで魅力的な機能の一つとしてマクロを紹介。
言語を拡張できることを説明し、具体例としては、(setq list (cons item list))のような頻出するものをユーザーレベルでpushとしてまとめられることを示す。
マクロのメリットとして、コンパイル時に展開することによる効率の高さと拡張性について触れ、個々のマクロはLispコンパイラの断片ともいえる、と述べる。 また、Lispでマクロがこれ程便利なのは、LispコードはLispデータであるということを説明し、PL/IやFORTRANではこれ程簡単に言語を拡張できないことを挙げる。
さらに、括弧で表現することに目を瞑れば、どんな拡張でもマクロ→素のLispという変換を使って書くことが可能ということと、その拡張した表現も効率よくコンパイルされうるということがマクロの最大の魅力としている。

最後にDavid Moon氏の

"Functions compute, macros translate."

という言葉を引用して締める。含蓄があるような無いような……。

結び

割と扇情的なところもあり、10年位Paul Graham氏の先取をしている所もあるなあと感じた。
全体的に面白い読み物ではないだろうか。


HTML generated by 3bmd in LispWorks 7.0.0

CADR System 78.52 其の二

Posted 2017-04-08 12:16:32 GMT

CADR System 78.52 — #:g1でams氏のプロジェクトを紹介したが、本プロジェクトは、LM-3/mit-cadrだそうで、ams氏のものは色々実験的なものだったらしい。

LM-3/mit-cadrの方を試してみたら、こちらはLinux版の場合は、これまでのようにSDLを利用するようになっていて、キーボード・マウスともに問題なく機能するようだ。

なお、usim -r ../../lispという風に明示的にシステムルートを指定する必要があるのは、現状こちらも同じらしい


HTML generated by 3bmd in LispWorks 7.0.0

Older entries (2108 remaining)