Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2011-07-17

DO&

| 16:16 | DO& - わだばLisperになる を含むブックマーク はてなブックマーク - DO& - わだばLisperになる

いつものごとく古いLispマシンのメーリングリストを漁っていたところDO&というものの提案メールを発見しました。

Date: Wednesday, 21 April 1982, 20:15-EST
From: levitt at MIT-AI, zvona at MIT-AI
Sender: Zvona at MIT-AI
Subject: LMLIB;DO&
To: info-lispm at MIT-AI

DO& is an interation macro with many of the features of LOOP and a
LISPy syntax similar to DO*.  User-definable keywords allow common
iterative constructs -- like CDRing down a list, CONSing a new list,
or counting -- to be implemented more simply and readably.  Automatic
generation of end tests makes the DO/DO* end-test form unnecessary.

The programs below, equivalent to common LISP functions, give a feel for
DO& style:

(defun length (list)
  (do& ((i &count0)
	(l &pop list &return i))))

(defun reverse (list)
  (do& ((elt &pop list &return accum)
	(accum &push elt))))

(defun listarray (array)
  (do& ((elt &aref array
	     &return (nreverse list))
	(list &push elt))))

(defun remq (item list)
  (do& ((a &pop list &return (nreverse out))
	(out &push a
	     &only-if (neq a item)))))

DO& allows most relevant information to appear within the
variable specifications, improving program clarity, and doing
away with the need for formulaic and complex bodies.

DO& has evolved over more than two years and reimplemented many times.
The rough corners have been worn off, and we now believe the current
implementation is clean enough for general release.

DO& is documented in detail in LMLIB;DO&DOC.  Bugs to BUG-DO&@AI;
users may wish to add themselves to INFO-DO&.

Here is a partial comparison of features of DO& and LOOP.  It is
perhaps not perfectly impartial.  Also, many of the features of LOOP
which DO& lacks could be added if there were demand for them.

DO& syntax is a natural extension of DO*.  LOOP is a non-LISPy
sublanguage.  Partly as a consequence, it is easier to determine
the scope of DO& keywords than that of LOOP keywords.  Since
keywords all begin with ``&'' it is easy to separate them from
non-keywords.  The simplicity of DO& syntax makes it trivial to
learn and often immediately understandably by non-users.  Also it
indents better than LOOP in Zmacs.

LOOP and DO& have roughly comparable numbers predefined iteration
keywords.  The sets are not identical; LOOP has a package mapping
keyword, and DO& has one for mapping over plists.  In any case, both
make it relatively easy to define your own keywords, so exactly which
keywords are defined by default is not very important.

LOOP supports parallel binding; DO& does not.  Of course you can
always use an extra variable to get the same effect.

DO& guarantees that variables have sensible values at all times; LOOP
does not.  In particular, in a LOOP epilogue, the values of iteration
variables may be undefined, whereas in a DO& &RETURN form, they are
always defined and take on the obvious value.

Both LOOP and DO& achieve package independence by using pname equality
in looking for keywords.

LOOP supports destructuring; DO& does not.  DO& generates automatic
dummy variables when none is supplied in a variable specification;
LOOP does not.

LOOP does more code optimization than DO& does.

DO& has many other features that are described in detail in DO&DOC.

LOOPマクロに対する対抗馬としては、最初期のものではないかと思いますが、LOOPで良く言われている問題点が既に述べられています。

面白そうなのでDO&のソースがどこかに落ちてないか探してみたのですが、残念ながらみつけることはできませんでした。

ということで、適当にサンプルコードが動く程度のものを作ってみました。

適当に考えながら作成していましたが、途中で面倒になったので、fare-matcherでやっつけることに。

しかし、サンプルコードの範囲だけではどういう動作なのかはちょっと分からないなという感じです…。

2010-10-10

(48) Lisp のプログラミング環境 (<大特集>新しいプログラミング環境)

| 23:27 | (48) Lisp のプログラミング環境 (新しいプログラミング環境) - わだばLisperになる を含むブックマーク はてなブックマーク - (48) Lisp のプログラミング環境 (新しいプログラミング環境) - わだばLisperになる

これまで紹介したもののなかにも論文の体裁ではないようなものがありましたが、CiNiiでは、情報処理学会の会誌「情報処理」の内容も無料で読めるようになっていて、その特集だったようです。

どちらにせよ面白い内容なので良いのですが、こういうのは文献といって紹介した方が良いのでしょうか。

今回は、

です。

情報処理 Vol. 30 No.4

は、プログラミング環境の特集のようですが、この特集では、LISPのプログラミング環境として、SymbolicsのGeneraと、XeroxのInterlisp-Dの当時の二大Lispマシンの環境を紹介しています。

かなり詳しく紹介されているのですが、現在のEmacs上の環境であるSLIMEより便利そうなところが散見され、やはり羨しいなあと思ってしまいます。

一度、これらのLispマシンの環境にどっぷりとつかってみたいものです。

2010-09-18

(47)“日本語上手”なCommon Lisp ~LispマシンExplorerでの実現~(1987)

| 19:40 | (47)“日本語上手”なCommon Lisp ~LispマシンExplorerでの実現~(1987) - わだばLisperになる を含むブックマーク はてなブックマーク - (47)“日本語上手”なCommon Lisp ~LispマシンExplorerでの実現~(1987) - わだばLisperになる

これまで、CiNiiを漁っていましたが、情報処理学会 電子図書館でも論文がPDFで公開されていて、さらにCiNiiで見付からない論文もあるので、CiNiiと合せて漁ってみることにしました。

今回は、

です。

Explorerとは、MITのCADRの流れのLispマシンですが、LMIのマシンから枝分かれしたもので、TIが開発し販売していました。

このTI Explorerを日本では、日本ユニバック(現日本ユニシス)(ググっても詳細が見付からないので間違ってるかも)が代理店となってKS-301という名前で販売していたようです。

この論文は、元々日本語を扱うことを考慮されていないTI Explorerで日本語を扱うことをテーマにしています。

文字の種類の多い日本語を扱えるようにした方法そのですが、主なところとしては、CLtL1時代まで仕様にあった、文字のフォント属性のビットをあれこれ工夫して実装したようです。

また、表示だけでなく、日本語の全角文字とシンボルの関係など意味論的にも色々と試行錯誤があって面白いです。

(eq 'lisp 'lisp)
;⇒ T

この日本語化された処理系は、Nippongo Common Lisp(NCL)とのこと。

ちなみに、この論文自体も日本語化されたTI Explorerで書かれたらしく、最後のページに日本語化されたZmacsのスクリーンショットで確認できます。

2009-09-21

electric-shift-lock-mode

| 23:52 | electric-shift-lock-mode - わだばLisperになる を含むブックマーク はてなブックマーク - electric-shift-lock-mode - わだばLisperになる

70年代後半位までLISPのソースは大文字で書かれているものが多いのですが、70年代後半に登場したLispマシンのエディタ(ZWEI/Zmacs)にも、そんな時代を反映した、Electric Shift Lockという機能があります。

これは、CAPSキーをオンにしてくれるようなモードで、Shiftを押さない状態が大文字、逆にShiftを押すと小文字というモードです。

気が効いているのは、文字列やコメント等、大文字と小文字を区別する必要がある場所では、通常通りShift押下で大文字になるというところ。

;; foo
(DEFUN FOO (N)
  "foo"
  (LIST N))

こんな感じのがすらすら簡単に書けます。

以前からEmacs上で自作してみたかったのですが、連休中にちょっと挑戦してみようと思いたちました。

しかし、既に前に同じものがあったら嫌だなあと思い、念の為ググってみたら、ずばりを見付けてしまいました(笑)

John Paul Wallingtonさんが、去年の5月に作られていたようです。こんなニッチすぎるところに目をつけるとは…。世界は狭い。

しかし、どうもWallingtonさん作の挙動は、Shiftを押しても小文字は出ず、全部大文字になるようです。

連休中は、ぼーっとこの辺りをLispマシン風の挙動に変えてみたいです。

いまどき大文字でコードを書くということも少ないですが、気分を変えて大文字ベースで書いてみるのも一興かもしれません。

SQLでなんとなくこのモードが使えるかと思ったりもしますが、微妙な気もします。

2009-01-21

demoプログラム起動篇

| 14:24 | demoプログラム起動篇 - わだばLisperになる を含むブックマーク はてなブックマーク - demoプログラム起動篇 - わだばLisperになる

今回は、デモプログラムを起動したところをキャプチャしてみました。

どうもfc2だと不適切な動画に判定されたようで、前回の動画が削除されてるみたいなんですが…。

アップしなおしてみたりしたのですが、削除されないことを祈ります(´▽`*)

最初の動画ですが、どうも途中から画像がおかしくなるみたいです。

YouTubeにアップも試してみているのですが、字がつぶれると観ても面白くないしなかなか微妙なところです。

2009-01-18

CADRをvnc2swfで録画してみました

| 22:13 | CADRをvnc2swfで録画してみました - わだばLisperになる を含むブックマーク はてなブックマーク - CADRをvnc2swfで録画してみました - わだばLisperになる

昨日のLispマシンエミュレータで遊んでみようという企画は、想像以上に困難がありなかなか思うように展開できませんでした。

やはり動画が必要か、ということでvnc2swfでCADRエミュレータを録画してみたところ、それなりに見れるようなので、これから何回かに渡って、「CADR生活」として動画をアップしてみることにしました。

今回は、かなり挙動不信な動きをしていますが、とりあえず様子見のデモということでアップしています。

起動、時刻入力、画面サイズを変更、Zmacs起動、ファイル開いてみる、無駄なマクロを書いて、そのマクロを展開して確認、flavorsでクラスを定義、インスペクタでインスタンスを確認、Diredを起動、バックアップファイルを削除、M-.でクロスリファレンス実行、(fed)でフォントエディタ起動、(hacks:worm)を起動するものの画面サイズが違うためか上手く動かず等々です。

今からすると、素朴ですが、30年前の環境であることを念頭に置きつつ眺めてみて頂けると嬉しいです。

まだまだ色々できるので、機能別に整理して紹介して行きたいと思っています。

はてなだとフラッシュの動画がアップできないのでfc2にページを作って動画を置いています。

2009-01-13

第29回CL勉強会CADR Lispマシンで遊んでみよう篇の準備物

| 22:23 | 第29回CL勉強会CADR Lispマシンで遊んでみよう篇の準備物 - わだばLisperになる を含むブックマーク はてなブックマーク - 第29回CL勉強会CADR Lispマシンで遊んでみよう篇の準備物 - わだばLisperになる

今週のCL勉強会は、PCLを読むのに加え、CADR Lispマシンのエミュレータで遊んでみようと思います。

CADR Lispマシンは30年前のLispマシンで、これから発展したSysmbolicsよりは素朴な感じなのですが、この時点でも結構面白く、そこそこLISPの開発環境としても使えたりします。

このCADR Lispマシンにはエミュレータがあり、下記のサイトから入手できます。

今回はこれをいじってみようという感じで、できれば、一緒に起動して遊んで貰いたいので事前にダウンロードして準備して頂けると嬉しいです。

外部のホストとファイルを共有すると面白さ倍増なので、今回は申し訳ないですが、対象OSはLinuxとしたいと思います。

しかし、Windows用のファイルも配布されていますので、外部とファイルのやりとりはできませんが、ログインしたりエディタを起動したりはできると思います。

今回必要なのは下記の3つのファイルです。

CADRシミュレータ本体:

http://www.unlambda.com/download/cadr/usim.tar.gz

ディスクイメージ:

http://www.unlambda.com/download/cadr/disk.img.tar.gz

Linuxとファイルをやりとりするためのサーバ:

http://www.unlambda.com/download/cadr/chaos-cadr.tar.gz

ちょっとマニアックなので私以外、誰も参加しない可能性もありますが、それはそれで淡々と進めて行きます(笑)

2009-01-05

Lispマシンのクロージャ

| 00:16 | Lispマシンのクロージャ - わだばLisperになる を含むブックマーク はてなブックマーク - Lispマシンのクロージャ - わだばLisperになる

Lispマシンのマニュアルを眺めていてクロージャの説明の項にこんなコードがありました。

(deff print-in-base-16
      (let ((*print-base* 16.))
        (closure '(*print-base*) 'print)))

(print-in-base-16 64)
;>> 40
;=> 64

Common Lispで書くなら、こんな感じです。

(setf (symbol-function 'print-in-base-16)
      (let ((*print-base* 16)) 
        #'print))

おお、なるほど、こんな書き方があったかと思ったのですが、良く考えるとCommon Lispだと、*print-base*はスペシャル変数なので閉じ込められません。

(print-in-base-16 64)
;>> 64
;=> 64

しかし普通に

(defun print-in-base-16 (num)
  (let ((*print-base* 16))
    (print num)))

(print-in-base-16 64)
;>> 40
;=> 64

と書いておけば良く、これならLispマシンでもCommon Lispでも同じ動作で、どちらかというとLispマシンの例がトリッキーな気もします。

しかし、

;; /tmpのファイルをファイル名だけで読める
(defun load-in-tmp (file)
  (let ((*default-pathname-defaults* #P"/tmp/"))
    (load file)))

のように色々工夫できることを教えられた気がするので、とりあえず良かったかなと。

ちなみに、LispマシンのLISPは、Zetalispなのですが、基本的にダイナミックスコープで、クロージャは特殊な構文を使って実現します(上のclosureという構文)。

2008-10-10

Flavorsとデザインパターン - Template Method

| 05:18 | Flavorsとデザインパターン - Template Method - わだばLisperになる を含むブックマーク はてなブックマーク - Flavorsとデザインパターン - Template Method - わだばLisperになる

最近Lispマシンのエミュレータを触ってないので、Flavorsでデザインパターンネタはどうかなと思って書いてみました。

とりあえず先日のTemplate Methodです。

Flavorsは、メソッドがクラス属していて、マルチメソッドでもないので、Javaの例を写すにもなんとなくしっくりくる気もします。

CADRエミュレータのFlavorsは最初期のもので、sendの代わりに<-を使用します。

ちなみに、この時期は、<-とfuncallは同じもので、インスタンスをfuncallしてもOKで、(funcall-self 'key)という構文もあり、(<- self 'key)と同じです。

キーワードに一々quoteを付けないといけないのですが、ソースのコメント等では、quoteは無く、この辺が歴史的変遷というか、謎の一つです。

さらにちなむと、Allegro CLには、Flavorsが付いてくるので、AllegroのFlavorsで遊んでみるのも一興かもしれません。

(defflavor abstract () ())

(defmethod (abstract :template-method) (str)
  (<- self ':op2 (<- self ':op1 str)))

(defflavor concrate () (abstract))

(defmethod (concrate :op1) (str)
  (string-upcase str))

(defmethod (concrate :op2) (str)
  (string-reverse str))

(<- (make-instance 'concrate) ':template-method "foo")
;=> OOF

(defflavor concrate2 () (abstract))

(defmethod (concrate2 :op1) (str)
  (string-pluralize str))

(defmethod (concrate2 :op2) (str)
  (string-reverse str))

(<- (make-instance 'concrate2) ':template-method "foo")

;=> soof

2008-06-15

LispマシンとCDR-Coding

| 14:50 | LispマシンとCDR-Coding - わだばLisperになる を含むブックマーク はてなブックマーク - LispマシンとCDR-Coding - わだばLisperになる

今回の勉強会でLispマシンを取り上げてみたのですが、zickさんのブログエントリでの反応で、CDR-Codingについて言及がありました。

「Lispマシンといえば、CDRコーディング」というというところがマニアックかつ正統派というか凄いですね(笑)

CDR-Codingについては、Lispマシンの最初のレポートにも記述がありまして、割と目玉なところだったようです。

今回自分もこのAIM-444を読んでみて、色々発見があったのですが、Lispマシンについてだけでなく、Lisp-machine Lispがどういう風に実装されていたかを知る資料としても面白いものかと思います。

今回勉強会で言及していないものは沢山あるのですが、「スタック」、「CDR-Coding」、「タグアーキテクチャとLISP」等は目玉のところかなと思いますし、LISP処理系を作る人にも面白い読み物かなと思いますのでお勧めです。

また、CDR-Codingについては、GLSがAI Memoで詳しく解説しているものがあってこれも面白いです。

2008-05-08

CADRでFLAVORS

| 16:10 | CADRでFLAVORS - わだばLisperになる を含むブックマーク はてなブックマーク - CADRでFLAVORS - わだばLisperになる

CADRエミュレータで何かしようと思いつつも前回からまた一ヶ月経ってしまいました。

最近CLOSのような、LISP上でのOOPになんとなく興味があるのですが、CADRには、CLOS以前のflavorsというOOPの枠組がありました。

よくRubyなどで、mixinとかいう用語が使われますが、この用語は、確かflavorsに由来していたと思います。

アイスクリームのトッピングに由来した用語なのですが、flavorsという名前自体、そのトッピングのことを指してるみたいです。

とりあえず、何から始めたら良いか良く分からないので、ポール・グレアム著のANSI CLのCLOSの章をなぞってみることにしました。

とりあえず、構造体とクラスを比較してみる、という内容なのですが、defstructの細かいところが、CLとLisp Machine Lispで違っていたりして、それもまた乙です。

とりあえず、CLの構造体だとこんな感じです。

;; CL
(defstruct rectangle
  height
  width)

(defstruct circle
  radius)

(defun area (x)
  (cond ((rectangle-p x)
         (* (rectangle-height x) (rectangle-width x)))
        ((circle-p x)
         (* pi (expt (circle-radius x) 2)))))

(let ((r (make-rectangle)))
  (setf (rectangle-height r) 2
        (rectangle-width r) 3)
  (area r))
;=> 6

自動で、rectangle-widthのようなアクセサを作ってくれて、rectangle-pのような述語も作成してくれます。

次にLisp Machine Lispでの構造体でのバージョンです。

;; Lisp Machine Lisp
(defstruct (rectangle :named)
  rectangle-height
  rectangle-width)

;; アクセッサはフルネームじゃないと駄目
;; namedにしないと、
;; (typep obj 'rectangle)とか効かないので、
;; namedで作らないとrectangle-pのようなものが作れないらしい。

(defstruct (circle :named)
  circle-radius)

;; piは定数ではないので定義
(defconst pi 3.141592653589793238)

;; 自動で、述語を作ってくれないので自作
(defmacro make-pred (name)
  `(defun ,(intern (string-append (string name) "-P")) (obj)
     (typep obj ',name)))

(make-pred rectangle)
(make-pred circle)

(defun area (x)
  (cond ((rectangle-p x)
         (* (rectangle-height x) (rectangle-width x)))
        ((circle-p x)
         (* pi (expt (circle-radius x) 2)))))

(let ((r (make-rectangle)))
  (setf (rectangle-height r) 2)
  (setf (rectangle-width r) 3)
  (area r))
;=> 6

そして、Lisp Machine LispのFlavorsで

;; Lisp Machine Lisp
(defflavor rectangle (height width) ()     
  :gettable-instance-variables
  :settable-instance-variables)

(defflavor circle (radius) ()
  :gettable-instance-variables
  :settable-instance-variables)

(defmethod (rectangle :area) ()
  (* (funcall-self ':height) (funcall-self ':width)))

(defmethod (circle :area) ()
  (* pi (expt (funcall-self ':radius) 2)))

(let ((r (make-instance 'rectangle)))
  (<<-- r
        (':set-height 2)
        (':set-width 3)
        (':area)))
;=> 6

ざっとした説明ですが、まず、キーワードに一々クオートが付いています。

これは、Lisp Machine Lispでは、CLのようにキーワードパッケージがあって、そのシンボルの評価結果が自分自身となるようなものではなく、ただの目印的なものなので、クオートが必要になります。

次に、defflavorですが、これは、CLOSのdefclassに相当します。

書式は、

(defflavor クラス(フレイバー)名 (スーパークラス)
  ...)

のような感じで、

:gettable-instance-variables

:settable-instance-variables

:inittable-instance

は値を取得/設定/初期化できるようにする指示で、デフォルト値も設定できます。

とりあえず、フレーバーを作ったら、

(setq r (make-instance 'rectangle))

(<- r ':set-width 3)

のようにして、値を設定できたりします。

rというオブジェクトに:set-widthと3というメッセージを送るのですが、

(funcall r ':set-width 3)

でも良かったりするみたいです。

ちなみに<-は後に、sendという名前になったようです。

set-〜というところは、
settable-instance-variablesをすると自動的に:set-〜で値を設定することができるようになります。

それで、defmethodですが、

(defmethod (フレーバー キー?) (引数)
  ...)

となり、CLのdefmethodとはちょっと違っています。

呼び出し方ですが、

(<- r ':area)

のようになるようです。

funcall-selfですが、defmethod内では自身を指すselfという変数が使えるので、これは、(<- self ...mesg)と同じことのようです。

CLOSのように(area r)とは書けないみたいでなんですが、初期のFlavorsの試行錯誤の後、「関数呼び出しの形とメソッド呼び出しの形を一緒にしたら良いんじゃないか?」というアイディアが現われて形が統合されたらしいです。

<<--は、(progn (<- ..) (<- ..))に展開されるマクロで上の例は、

(let ((r (make-instance 'rectangle)))
  (<- r ':set-height 2)
  (<- r ':set-width 3)
  (<- r ':area))

と同じです。

まとめ

という感じで、自分も全然分かっていないので、解説らしい解説にもなっていないのですが、色々いじって遊んでみようと思っています!

2008-04-03

またふらふらとCADRでなにかする

| 19:08 | またふらふらとCADRでなにかする - わだばLisperになる を含むブックマーク はてなブックマーク - またふらふらとCADRでなにかする - わだばLisperになる

メインの環境を64bit Linuxにしてから、CADRエミュレータが上手く動かなくなっていたので放置していたのですが、Ubuntuの場合ia32-libsをインストールすれば、面倒もなく32bit版で動くことが分かったので、またいじり始めてみることにしました。

以前のエントリでは、ダウンロードから導入、ちょっとした開発環境の説明を書きました(CADRカテゴリーに纏めてあります)が、

今年は、もう一歩踏み込んでみたいところ。

目標としては、Flavorsなどを使ってプログラミングするところ位まで探究できたら良いなと思っています。

配布されているMIT CADRエミュレータの場合、初期のマニュアルに説明のある機能が無かったりしますので、結構初期のLisp Machine Lispのようです。

とりあえず今日は久し振りに使ってみるということで、前々から試してみたかった、ZMACSへのコマンドの追加を試してみたいと思います。

ZMACSは、Lispマシンで動くEMACSで、オリジナルのEMACSとほとんど同時期の1976年に開発がスタートしたようです。

最初は、EINE(Eine Is Not EMACS)という名前で、その後、ZWEI(Zwei Was Eine Initially)という名前になり、Zmacsへ、という流れになります。

Lispマシンは全面的にLispで記述されているので、当然その上で動くZMACSもLispで記述されています。LISPで記述されているということは、最初からLISPで拡張可能なわけで、恐らくLISPで拡張可能なエディタとしては、ZMACSが一番最初のものなのではないでしょうか。Multics EMACSは、1978年で、Multics EMACSの作者もZMACSの方が先に存在してたと言ってましたし…。

それはさておきZMACSの拡張コマンドですが、DEFCOMという対話操作拡張用のマクロが用意されているのでそれを使ってみます。

作るコマンドですが、自分は、普段ダブルクオートをM-"のキーバインドで、対で入力しています。

EMACSでは、幾つかこの様な入力方法を実現する方法があるのですが、ZWEIにもCOM-MAKE-()という、括弧を対で入力する関数があるので、これをちょっといじって作ってみました。

この関数は数引数を受けとることにより、任意の式をまたいで囲むことができます。

(pkg-bind "zwei"
  (DEFCOM COM-MAKE-/"/" "Insert matching delimiters, putting point between them.
With an argument, puts that many s-exprs within the new /"/"." ()
    (LET ((OPEN #/") (CLOSE #/")
          (MOVER 'FORWARD-SEXP) (POINT (POINT)))
      (DO ((CH (LDB %%CH-CHAR *LAST-COMMAND-CHAR*))
           (L *MATCHING-DELIMITER-LIST* (CDR L)))
          ((NULL L))
        (COND ((OR (= CH (CAAR L)) (= CH (CADAR L)))
               (SETQ OPEN (CAAR L) CLOSE (CADAR L) MOVER (CADDAR L))
               (RETURN T))))
      (LET ((BP (IF *NUMERIC-ARG-P*
                    (OR (IF (EQ MOVER 'FORWARD-SEXP)
                            (FORWARD-SEXP POINT *NUMERIC-ARG* NIL 0 NIL T T)    ;No UP
                          (FUNCALL MOVER POINT *NUMERIC-ARG*))
                        (BARF))
                  POINT)))
        (AND (MINUSP *NUMERIC-ARG*) (PSETQ BP POINT POINT BP))
        (INSERT BP (IN-CURRENT-FONT CLOSE))
        (INSERT-MOVING POINT (IN-CURRENT-FONT OPEN))
        DIS-TEXT)))
  )

ちょっとした説明

  • EMACSとZMACSの違い

上記のコードを眺めるとGNU Emacsとは結構違っていることが分かると思います。Hemlockや、LispWorksのエディタ、Climacs等これに近いのですが、恐らく、ZMACSから影響を受けていて、ZMACS系とも呼べると思います。

  • pkg-bind
    • ボディ部は指定したパッケージ内で評価されます。上記の場合、"ZWEI"パッケージ内で評価されています。Lispマシンの場合、ファイルの一行目にパッケージを記述することで、指定することができるのですが、この方法を発見したので試しに使ってみています。

それで、定義した関数をどうっやってキーバインドに割り付けるかですが、

割り付けには、SET-COMTABやSET-COMTAB-RETURN-UNDOを使用します。

自分は、初期化ファイルで設定するので、ログアウトしたらアンドゥされるように、SET-COMTAB-RETURN-UNDOを使ってみています。

(login-eval
 zwei:(set-comtab-return-undo *standard-comtab* '(#^C/" com-make-/"/"))) ;^Cはコントロール文字

という風にホームディレクトリのlispm.initに記述すれば、M-"でcom-make-""が呼び出されるようにログイン時に初期化されます。

ちなみに、パッケージの指定方法が不思議な感じになっていますが、こういう風にも書けたみたいです。

zwei:(set-comtab-return-undo *standard-comtab* '(#^C/" com-make-/"/"))
=>
(zwei:set-comtab-return-undo zwei:*standard-comtab* '(#^C/" zwei:com-make-/"/"))

ということのようなのですが詳細はまだ、良く分かっていません。pkg-bindの略記方法なのかもしれませんが、便利といえば便利なような。

という感じで、ふらふらとしばらくMIT CADRを使ってみようと思います。

2008-01-10

TIのLispマシン - TI-Explorerのエミュレータ

| 15:00 | TIのLispマシン - TI-Explorerのエミュレータ - わだばLisperになる を含むブックマーク はてなブックマーク - TIのLispマシン - TI-Explorerのエミュレータ - わだばLisperになる

Lispマシンというのは、ある意味Lisp文化の頂点の一つだったんじゃないかと思うのですが、今年は、Lispマシン近辺をもう少し探索してみたいなと思い、手始めに、これまで、別のブログに書いていたLispマシン関連の記事もこのブログにカテゴリ:「Lispマシン」として纏めてみることにしました。

これまでは、MIT CADRや、INTERLISP-Dを、ちょっといじったりしてました。結構情報は古くなってしまったんですが…。

それで、今回は、TI-Explorerのエミュレータの導入をまとめてみることにしました。

TI Explorerとは

テキサスインスツルメンツも昔はLispマシンを製造していまして、その名をExplorerといいました。

これは、Greenbratt氏のLMIからライセンスを受けて製造されていたマシンということで、LMI系のLispマシンです。

MITのCADRを起源としているので共通点は非常に多いのですが、それなりに違いはあります。

このTI Explorerのエミュレータを開発して配布しているところがあるので、ありがたく使わせて頂きます。

Merokoという名前のようです。

なんか、日本のアニメのキャラから名前がとられているっぽいのですが、元ネタが分からない…。

インストール

ここでは、Ubuntu 7.10 x86_64にインストールする方法を書きます。

もともとコンパイル済みのLinux用のバイナリが同梱されているので、32bit環境ならば何もしなくても起動できるとは思います。

  • ダウンロード
$ wget http://www.unlambda.com/download/meroko/meroko-20060610.tar.gz
$ wget http://www.unlambda.com/download/meroko/X1-DISKS.tgz
  • 解凍
tar zxvf X1-DISKS.tgz
tar zxvf meroko-20060610.tar.gz

解凍するとsvnフォルダができます。この中に、ソースと実行バイナリがあります。

自分は、x86_64用にMakefileを書き換えて、コンパイルしなおしてみています。といってもCPUの指定を変更するだけです。

--- svn/Makefile        2006-06-11 23:57:03.000000000 +0900
+++ /share/sys/emu/Explorer64.emu/svn/Makefile  2007-12-22 07:49:53.000000000 +0900
@@ -15,7 +15,7 @@
 DISPLAY_OBJ = sdl.o
 endif
 
-CFLAGS= -O3 -ggdb -Wall -march=pentium3 -mfpmath=sse -mmmx -msse $(DEFINES) -DENABLE_ENET
+CFLAGS= -O3 -ggdb -Wall -mfpmath=sse -mmmx -msse -msse2 -msse3 $(DEFINES) -DENABLE_ENET
 # -DTRACELOG
 # -DDEI_TRACELOG
 # -DTRACELOG2

コンパイルすると、merokoという実行ファイルができるのでこれを直接実行します。

実行ファイルと同じディレクトリにディスクイメージを解凍してできたX1-DISKSディレクトリを移動します。デフォルトだと1階層上にMerokoというディレクトリを作成してそこに置くみたいですが、同じディレクトリに配置することにしてみます。

いじってみる

./meroko

で起動します。

  • 起動時に何やら質問されるのですが、とりあえず、D=Default。
  • ネットワーク関連で色々文句を言われるのですが、とりあえず無視。Ctrl-Zでトップレベルに抜けられます。
  • リスナーが立ち上がっている状態なので、ここに色々式を入力します、たとえば、(ed)でZmacsが起動します。
  • ホームディレクトリの作成
(fs:create-directory ";g000001")

";"がパスネームセパレータの様です。この場合、ルートディレクトリ直下にg000001というディレクトリを作成します。

  • ログイン
(login 'ユーザ名)

で、ログインします。デフォルトでは、ルート直下の同じログイン名と同じ名前のディレクトリがホームディレクトリとして利用されます。

ログイン初期化ファイルを作成する

リスナーに(ed)と打込むか、System Eでエディタが起動します。エミュレータでは、Systemは、F1にアサインされています。(E→エディタ、L→リスナー、P→Peek(PSのようなもの)、M→メーラ)

Zmacsが起動するので、自分用のログイン初期化ファイルを作成してみましょう。

ファイル名は、login-init.lispで、

Emacsと同様にC-X C-Fで作成します。

ログインされると、この中のLispの式が評価されます。

とりあえず、簡単なところで、自分は、

(tv:black-on-white) 
(ed "g000001;gazonk.del")

のようにしています。

black-on-whiteは、画面を黒地に白にする命令で、ed〜は、ログインしたら、Zmacsで、gazonk.delというファイルを開けということです。

大体こんな感じなのですが、基本的なEmacsの機能は大体あるので、色々試してみると面白いかと思います。

Lispの開発もSlimeのようにかなり対話的に行なえます。エディタ上の式を評価するには、C-Shift-E、コンパイルするには、C-Shift-Cです。画面のエコーエリアか、長い場合は、画面の上から、スルスルと結果が表示されてきます。これが結構良い感じで、SLIMEもこういう風に表示できたら良いのにな、とか思います。

マニュアルとかシステムのソースとか

膨大なマニュアルがbitsaversに保管されています。

システムコードの一部がウェブで公開されています

まとめ

以上、非常に簡単にですが、インストールからログイン位までで、自分の知っていることを書いてみました。

Lispマシンってどんな感じだったのか雰囲気位は、感じられるかと思います。

SymbolicsのLispマシンはもっと凄くて、TI Explorerより、もっと洗練されていて驚く程、高機能です。ただ、エミュレータは公開されているものの本格的に利用するには、Symbolicsのソースが必要なようです。こちらも、ちょっと起動するところまではできたので、そのうち纏めて書いてみたいと思います。

このエミュレータは重たくて、Core2位でないと使いものにならないかもしれません。また、どうやら外部とネットワークで通信もできるようなのですが、ドキュメントも少なく自分は、まだ使いこなせてません。もし、なにか情報お持ちでしたら、ツッコミ等大歓迎です!

2007-07-19

CADRエミュレータ (4) Lispの開発環境

| 23:09 | CADRエミュレータ (4) Lispの開発環境 - わだばLisperになる を含むブックマーク はてなブックマーク - CADRエミュレータ (4) Lispの開発環境 - わだばLisperになる

とりあえず、外部とのファイルのやりとりもできるようになりました。

折角のLispマシンなので、Lispを書いて遊びたいところだと思うので、CADRのLisp開発環境について書きたいと思います。

この辺からは、自分がLispの開発の経験がある訳でもなくLisp自体に詳しい訳でもないので、詳しいことは全く分かりませんので、かなり適当なことを書いている可能性も高いですが、とりあえず、自分が遊んでみたところを書いてみたいと思います。

コードを書く

これはZmacs上でEmacsと同じ感覚でファイル作成/編集ができます。Emacs上でのLispコードの操作ということに関しては、70年代のITS Emacs、Zmacsの時点でほぼ完成しているということなのかもしれません。

インタラクティブに書きたいんじゃ

これは、編集中のコードを評価することによってEmacsのinferior lisp modeの様な感覚でコードを書くことができるかと思います。評価された結果は、エコーエリアに表示されます。

Eval Defun (Control-Shift-E (Control-Hyper-E))

で、式を評価、

Compile Defun (Control-Shift-C (Control-Hyper-C))

で、式をコンパイルのようです。

評価した結果にエラーがある場合は、デバッガが起動します。デバッガから抜けるには、C-zを押します。

という感じで、自分などは、大したものを書く訳でもなく、書けるわけでもないので、エディタ上から式が評価できるだけで十分遊べます。

ヘルプ

とりあえずのところとしては、

Documentation (Control-Meta-?)

があります。

Control-Meta-?を押して実行すると、

Doc A,C,D,L,V,W,<space>,?:

となるので、適宜調べたい内容に応じてキーを選択します。

AとspaceはAproposの実行 (Emacsでもapropos)

Cは、Document Command (Emacsでのdescribe-key)

D、Describe Command (Emacsでのdescribe-function)

L、詳細不明です。

V、Variable 変数のApropos

W、Where Is / どのキーコンビネーションに割り当てられているか

という感じです。

他にも、M-.等々Emacsでもお馴染の機能があるので、試してみると面白いかと思います。