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-04-03

MIT CSAIL Tape Archives

| 00:23 | MIT CSAIL Tape Archives - わだばLisperになる を含むブックマーク はてなブックマーク - MIT CSAIL Tape Archives - わだばLisperになる

LetSのコードをいじっていて、MacLISPの PRINENDLINE という変数を調べていた途中でMIT CSAIL Tape Archivesというのを発見しました。

MITのCSAILで80年代に稼動していたTOPS-20のデータを公開しよう、というプロジェクトのようです。

いまのところSICPで有名なサスマン氏等がデータの公開に応じていて、1983年位のMacLISP上で動くScheme処理系(R3RSあたり?)のソースを見ることができる様子。

スタンフォード大学のSAILでも似たようなプロジェクトがありますが、

こういうのは、どしどし公開して貰えると一部のマニアは喜ぶと思います

2011-03-28

CMU AIレポジトリ探検 (4) Artificial Flavors

| 19:07 | CMU AIレポジトリ探検 (4) Artificial Flavors - わだばLisperになる を含むブックマーク はてなブックマーク - CMU AIレポジトリ探検 (4) Artificial Flavors - わだばLisperになる

特に決まった順番もなく彷徨っておりますが、今回は、CLOS関係の階層からArtificial Flavorsです。

Flavorsとは、CLOS以前のオブジェクト指向プログラミングの仕組みで、Smalltalkから影響を受けて作られました。

というよりもMITのLISPマシン自体がかなりAltoに影響を受けていたようですし、PARCとも交流があったようです。

Flavorsには、Smalltalkから強く影響を受けている初期のものと、80年代中後半CLにオブジェクト指向システムを加えようというときにSymbolicsが提案した総称関数ベースのNew Flavorsとがありますが、今回のArtificial Flavorsは、New Flavorsっぽい感じになります。

実際のところNew Flavorsっぽいというよりは、CLOSにちょっとマクロを被せただけ、という感じです。

Artificial Flavorsを使うとこんな感じに書けます。

(in-package :artificial-flavors)

(defflavor rectangle (height width) ()
  :readable-instance-variables
  :writable-instance-variables
  :initable-instance-variables)

(defmethod (area rectangle) ()
  (* (rectangle-height self)
     (rectangle-width self)))

;; => マクロ展開
(CL:DEFMETHOD AREA ((SELF RECTANGLE))
  (SYMBOL-MACROLET ((HEIGHT (SLOT-VALUE SELF 'HEIGHT))
                    (WIDTH (SLOT-VALUE SELF 'WIDTH)))
    (* (RECTANGLE-HEIGHT SELF) (RECTANGLE-WIDTH SELF))))

;; Flavorのスロット名で参照できるので短かくも書ける
(defmethod (area rectangle) ()
  (* height width))

(let ((rect (make-instance 'rectangle :height 3 :width 4)))
  (area rect))
;=> 12

deffravorの :readable-instance-variables、 :writable-instance-variables、 :initable-instance-variablesというのは、指定するとdefstructのようにセッターやゲッターの設定を自動でしてくれるというものです。

defmethodも少し書式が違っていて、ボディ内ではSELFやスロット名で変数を呼び出せたりできるようです。

紹介ついでにASDFに対応させ、処理系依存っぽいところは、Closer to MOPを使うように修正したものをgithubに上げてみました

適切に設定すれば、

(ql:quickload :artificial-flavors)

でロードできます。

ちなみに、Allegro CLには、より本格的なFlavorsが付いてくるようですので興味のある方は遊んでみると良いかなと思います。

2011-03-27

CMU AIレポジトリ探検 (3) Uranus

| 23:14 | CMU AIレポジトリ探検 (3) Uranus - わだばLisperになる を含むブックマーク はてなブックマーク - CMU AIレポジトリ探検 (3) Uranus - わだばLisperになる

Uranusについては以前も取り上げたことがありましたが、

これもAIレポジトリで配布されているので再度紹介してみることにしました。

Uranusとは多重世界機構というものを持つS式で記述するPrologです

もともとの実装は、UtiLisp上で動くものでProlog/KRという名称だったようですが、Lispマシン(Zetalisp)上に移植したのを機にUranusと名称を変更したようです。

Prolog/KRについては書籍も発行されていて詳しく知ることができます

自分もAmazonで買って読んでみましたがUranus以外のことも色々書いてあって興味深い内容でした。

このUranusですが、

からダウンロードできるようになっています。

CLtL1までは対応しているようなのですが、紹介ついでに以前Zetalisp的なところをCL風にしてasdファイルをつけてSBCLで動くようにしたものをgithubに上げてみました。

適切に設定すれば、

(ql:quickload :uranus)

でロードできます。

元のソースには、Zmacs用のUranusモード等も付いてくるのでSLIMEで再現してみたいなーなどと思いつつまったく進んでいません…。

妙な変更を加えてしまっているところもあると思いますのでみつけたら教えて頂けると嬉しいです。

2011-03-20

CMU AIレポジトリ探検 (2) Source Compare

| 10:59 | CMU AIレポジトリ探検 (2) Source Compare - わだばLisperになる を含むブックマーク はてなブックマーク - CMU AIレポジトリ探検 (2) Source Compare - わだばLisperになる

かれこれ20年程前のCMUでは、CLでポータブルに利用できる開発ツールがないことをどうにかしようというLisp-Utilitiesというプロジェクトがあったようです。

Symbolicsや、XeroxのLISPマシンでは当時でも色々揃っており、開発ツール自体がなかった訳ではないので処理系を跨いでポータブルであることが主眼だった様子。

Mark Kantrowitz氏が中心人物のようで、

CMU-CS-91-143

Portable Utilities for Common Lisp: User Guide & Implementation Notes

Mark Kantrowitz

May 1991

74 pages

というレポートに6つのツールの内容が纏められています(自分もどこから拾ってきたのか分かりませんが、現在はダウンロードできるリンクがみつけられませんでした)

上記のレポートによれば、このプロジェクトの成果物は一式でダウンロードできるようですが、現在まとまってダウンロードできるところは消滅している様子。

しかし探してみるとCMUのAIリポジトリでそれぞれのツールが単体で配布されていることをみつけました。

今回は、その内の一つであるSource Compareについてです。

内容は、このリンクから分かると思いますが、所謂diffです。

(sc:source-compare "cadr78/lispm2/let.lisp.1" "cadr99/sys2/let.lisp.1")

のようにすると、

===========================================================================
Source compare of cadr78/lispm2/let.lisp.1 with cadr99/sys2/let.lisp.1
===========================================================================
14c14
**** File cadr78/lispm2/let.lisp.1, After "(remprop 'let* 'source-file-name)"
< (defmacro let (pairs . body)
<        (do ((pairs pairs (cdr pairs))
---
**** File cadr99/sys2/let.lisp.1, After "(remprop 'let* 'source-file-name)"
> (defmacro let (pairs &body body)
>        (do ((pairs pairs (cdr pairs))
===========================================================================
115c115
**** File cadr78/lispm2/let.lisp.1, After "(defun let-macro-hair (pattern code cell)"
< (defmacro let* (pairs . body)
<        (do ((a (reverse pairs) (cdr a))
---
**** File cadr99/sys2/let.lisp.1, After "(defun let-macro-hair (pattern code cell)"
> (defmacro let* (pairs &body body)
>        (do ((a (reverse pairs) (cdr a))
===========================================================================
Done.

のように結果が出力されます。

LISPのコメントを無視できたりしてLISPフレンドリーなのが長所でしょうか。(オプションで挙動を変更できます)

ちなみに、同じファイルをdiff -uすると、

diff -u cadr78/lispm2/let.lisp.1 cadr99/sys2/let.lisp.1
--- cadr/lispm2/let.lisp.1       2009-01-03 09:28:22.000000000 +0900
+++ cadr99/sys2/let.lisp.1       2009-01-03 14:37:00.000000000 +0900
@@ -1,4 +1,4 @@
-;;;-*- Mode: Lisp; Package: System-Internals -*-
+;;;-*- Mode:LISP; Package:SYSTEM-INTERNALS; Base:8 -*-

 ;; Destructuring DEFUN must be added to this at some point.

@@ -11,7 +11,7 @@
 (remprop 'let 'source-file-name)
 (remprop 'let* 'source-file-name)

-(defmacro let (pairs . body)
+(defmacro let (pairs &body body)
        (do ((pairs pairs (cdr pairs))
            (vars nil)
            (let-macro-vals nil)
@@ -112,7 +112,7 @@
               (let-macro-get-last-var (car pattern))
               (let-macro-get-last-var (cdr pattern))))))

-(defmacro let* (pairs . body)
+(defmacro let* (pairs &body body)
        (do ((a (reverse pairs) (cdr a))
            (b body `((let (,(car a)) . ,b))))
           ((null a)

こんな感じになります。

紹介ついでに、ASDF対応にして、githubにアップしてみました。

適切な場所に、

git clone git://github.com/g000001/source-compare.git

すれば、

;; quicklisp
(ql:quickload :source-compare)

できると思います。

2011-03-18

CMU AIレポジトリ探検 (1) VGRIND

| 18:55 | CMU AIレポジトリ探検 (1) VGRIND - わだばLisperになる を含むブックマーク はてなブックマーク - CMU AIレポジトリ探検 (1) VGRIND - わだばLisperになる

もうかれこれ15年位は更新されている様子がないのですが、CMU Artificial Intelligence Repositoryというカーネギー・メロン大学が公開しているAI関係のレポジトリがあります。

ここにはAIレポジトリというだけあってLISP関係のものも多く眠っています。

以前からこれを一通り確認してみたいと思っていたので確認の記録をつけてみることにしました。

適当に目についたところから眺めてみようかなと思いますが、今回は、VGRINDというのを眺めてみます。

中身は、1つのファイルですが

http://www-2.cs.cmu.edu/afs/cs/project/ai-repository/ai/lang/lisp/util/vgrind/vgrind.txt

一体何に使うのか不明です。

とりあえずvgrindをググってみると、プログラムを整形するフォーマッタの一種の様子。

Ubuntuでvgrindを探してみてもそのものずばりはありませんでしたが、名前が似ているlgrindというのを発見。

とりあえずこれで良いだろうということでインストール

sudo apt-get install lgrind

lgrindのヘルプを読みつつ、vgrind.txtの内容から適当に使い方を推測し、

$ lgrind -d vgrind.txt -lclisp /tmp/foo.lisp > /tmp/foo.tex
$ latex /tmp/foo.tex
$ evince foo.dvi

のようにしてみると整形されたコードが表示されます。

TeXが好きな方には良いかもしれません。

2010-11-16

car/cdrの別表記を考えてみた

| 21:05 | car/cdrの別表記を考えてみた - わだばLisperになる を含むブックマーク はてなブックマーク - car/cdrの別表記を考えてみた - わだばLisperになる

何万回目の再発明なのかは分かりませんが、carとcdrの別表記がふと浮びました。

carやcdrというより、どちらかというと、firstや、secondに由来する考えだと思いますが、carを、

(i '(1 2 3 4 5))
;=> 1

と書いたら楽なんじゃないかと。

それで、cdrは、

(ii> '(1 2 3 4))
;=> (2 3 4)

という風、

(caaar (cddr '(1 2 ((3 4) 5))))
;=> 3

のようなものも、元の関数名が短かいので

(i (i (i (iii> '(1 2 ((3 4) 5))))))
;=> 3

そんなに膨れません。

(i@i@i@iii> '(1 2 ((3 4) 5)))
;=> 3

みたいに合体して書けても良いかなと思います。

まあ、これは、パターンマッチとか

(destructuring-bind (a b ((c d) e))
                    '(1 2 ((3 4) 5))
  c)
;=> 3

みたいに書くと思いますが…

自分は、carやcdrの組み合わせは、精々caddr、cddr位までしか使わない感じです。

最初の3つ位までが楽に書ければ、それで良いのかなあとも思います。

(letS* ((i (Erange 1 10))
        (name (intern (format nil "~@R" i))))
  (Rlist (eval `(defun ,name (list) (nth ,(1- i) list)))))
;≡ (loop :for i :from 1 :to 10
;         :for name := (intern (format nil "~@R" i))
;         :collect (eval `(defun ,name (list) (nth ,(1- i) list))))

;=> (I II III IV V VI VII VIII IX X)

(letS* ((i (Erange 2 11))
        (name (intern (format nil "~@R>" i))))
  (Rlist 
   (eval `(defun ,name (list) (nthcdr ,(1- i) list)))))
;=> (II> III> IV> V> VI> VII> VIII> IX> X> XI>)

2010-09-01

重なったフィルターをLISPで左から右に簡潔で読み易く書きたい

| 22:28 | 重なったフィルターをLISPで左から右に簡潔で読み易く書きたい - わだばLisperになる を含むブックマーク はてなブックマーク - 重なったフィルターをLISPで左から右に簡潔で読み易く書きたい - わだばLisperになる

以前から良く考える問題ではあるのですが、今日、

(defun PARENTHIZE (str)
  (let ((rstr (reverse str)))
    (ppcre:regex-replace-all 
     "\\s"
     (write-to-string 
      (reduce (lambda (acc x)
                (cons x (list acc)))
              (subseq rstr 1)
              :initial-value (list (char rstr 0)))
      :pretty nil
      :escape nil)
     "")))
(PARENTHIZE "いろはにほへとちりぬるを")
;⇒ "(い(ろ(は(に(ほ(へ(と(ち(り(ぬ(る(を))))))))))))"

という非常にどうでも良い関数を書いていて、処理の流れが括弧の内側から外側に向っていくのが、やっぱりよみにくいかなあと思い、上手く書ける記法はないかと、色々考えてみました。

こんな風に書けば良いのか

(defun PARENTHIZE (str)
  (let* ((* (reverse str))
         (* (reduce (lambda (acc x)
                       (cons x (list acc)))
                     (subseq * 1)
                     :initial-value (list (char * 0))))
         (* (write-to-string * :pretty nil :escape nil))
         (* (ppcre:regex-replace-all "\\s" * "")))
    *))

こんなマクロを書いてみれば良いのか

(defmacro SEQ (&body body)
  `(LET* (,(mycl-util:group body 2))
     ,(car (last body 2))))
(defun PARENTHIZE (str)
  (seq
    * (reverse str)
    * (reduce (lambda (acc x)
                (cons x (list acc)))
              (subseq * 1)
              :initial-value (list (char * 0)))
    * (write-to-string * :pretty nil :escape nil)
    * (ppcre:regex-replace-all "\\s" * "")))

いや、やっぱりこう書けた方が編集には都合が良いか

(defun PARENTHIZE (str)
  (seq
    (* (reverse str))
    (* (reduce (lambda (acc x)
                 (cons x (list acc)))
               (subseq * 1)
               :initial-value (list (char * 0))))
    (* (write-to-string * :pretty nil :escape nil))
    (* (ppcre:regex-replace-all "\\s" * ""))))

いやいや、いっそこう書けた方が良いか

(defun PARENTHIZE (str)
  (seq
    (reverse str) => *
    (reduce (lambda (acc x)
              (cons x (list acc)))
            (subseq * 1)
            :initial-value (list (char * 0))) => *
    (write-to-string * :pretty nil :escape nil) => *
    (ppcre:regex-replace-all "\\s" * "")))

こういうフィルターを順次重ねてゆく感じの場面で、左から右に良い感じで記述できるような記法/マクロがあったら教えて欲しいです。

2009-12-12

IFのインデント

| 22:10 | IFのインデント - わだばLisperになる を含むブックマーク はてなブックマーク - IFのインデント - わだばLisperになる

REMOVE-FROM-TREE-IFのコードでIFのインデントが読み辛い…と書いていて、IFのインデントに関しての古のLispハッカー達がMLで議論していたのを思い出したので掲載してみます。(CADR System 99の>doc>if.answerより)

Lispマシン初期では、今のEmacs Lispのようにthen節とelse節のインデントが違っていたらしいのですが、いつの間にやら揃える派の人がLispマシンに変更を加えてしまい、それを元に戻したRMS(ずらす派)と揃える派のやりとりです。

Date: 16 February 1982 01:57-EST
From: Richard M. Stallman <RMS at MIT-AI>
To: BUG-LISPM at MIT-AI

Does anyone object to indenting the else-clauses in IF two spaces
less than the then-clause?

This was flushed, but nobody admitted to flushing it, and the only
response I got before was a favorable one.  Unless opinion is clearly
against it, I will reinstall it.
Date: Tuesday, 16 February 1982  16:03-EST
From: DLW at SCRC-TENEX

Yes, I object to the special indentation for IF.  Also, if you look at
various init files you can find other people who, like me, remove
the special indentation.  Moon does.  Daniel Weise does, and he told
me that most of the people that he works with do too.

I don't know who changed the default; I didn't even know that it had
been changed (since my environment is customized anyway).
LEVITT@MIT-AI 02/16/82 15:58:53 Re:  IF indentation syntax
To: RMS at MIT-AI

I recommended &BODY style indentation to BUG-LISPM for IF over a year
ago.  I strongly prefer it.  At the time, DLW pointed out that for
"parallel constructions", with just a pair of forms, the other way
makes more sense, but still I find that harder to read.  His was the
only response I got at the time, and of course it was never
implemented until you did it (I had little doubt) a while ago.

From whom did you obtain your consensus on IF indentation aesthetics?
Since I imagine many of us will want to use Symbolics bands in the
future, won't it be a big hassle for you to re-install things like
this every time they release a new band?  Maybe you start putting a
bunch of "patches" that users have said they like, but Symbolics
doesn't care to support, into LMLIB;, and announce them.  Isn't that
the current convention?
dcb@MIT-AI 02/16/82 09:39:27
To: RMS at MIT-AI

By all means PLEASE re-install it.
	dan
Date: 16 February 1982 09:25-EST
From: Gerald R. Barber <JerryB at MIT-AI>
To: RMS at MIT-AI

No.  I prefer that else clauses are indented differently that the then
clause, it helps distinquish the two.
Date: 16 February 1982 04:47-EST
From: George J. Carrette <GJC at MIT-MC>

Yes, I object. I never use more that one else clause, so I think it
looks silly to have (IF (FOO X) (BAR X) (BAZ X))  indent as
(IF (FOO X)
    (BAR X)
  (BAZ X))

It is pretty to have parens line-up as much as possible. Certainly
with C-M-F and C-M-B it is never a readability problem.
RWG@MIT-MC 02/16/82 05:06:10 Re: Indenting IF

I used to prefer maximally aligned parens, but given the evolution of
Lisp syntax, I now lean toward the higher information content possible
with less rigid indenting.  In the case of IF with one ELSE clause, I
initially bletched when I saw RMS's contour, then decided it was in
fact mnemonic:  the outcome consonant with the predicate indented
consonantly, and mutatis mutandis for the ELSE.
Date: 16 February 1982 03:13-EST
From: Alan Bawden <ALAN at MIT-MC>

I didn't flush it, but three cheers for whoever did!  I detest having my IF's
indent that way.  The only time I ever mentiond this in public I got a whole
room full of people jumping up and down hating it right along with me.  (I
recall DLW and DANIEL to be amoung them.)  Moon tells me that he also dislikes
it.
Date: Wednesday, 17 February 1982, 00:39-EST
From: David A. Moon <Moon at SCRC-TENEX>
Subject: IF indentation

I answered your previous query.  I don't like the different indentation
for the else clauses; however it's not quite that simple.  When I use
symmetrical IFs, which I nearly always use, I greatly prefer having the
THEN and the ELSE indented the same way.  When I use multiple-else-clause
IF, I indent it the new way you (I assume) thought of.  However, after
much consideration and experimentation I decided that I liked it better
for the automatic indenter to do it the old way, and I would type
control-Tab myself if I wanted it the new way.  Consequently I put something
in my init file to turn off the new mode.

Most people I happened to ask about this preferred it the old way, however
if you reinstall it I will continue to make my init file turn it off.
Date: 16 February 1982 21:55-EST
From: Andrew L. Ressler <ALR at MIT-ML>
Subject: IF Indentation

I like it.  If people want to turn it off in their inits I could
care less but I like it to be the default.
Andrew
GSB@MIT-ML 02/16/82 20:10:14 Re: IF clause indenting

I've developed the habit of using IF in the simple cases where
the "then" and "else" clauses are equivalent, and i just about
never use multiple "else" clauses, so have always preferred
having them indent equivalently.  Of course, not using multiple
"else" clauses is partly a response to having it not supported
everywhere (once-upon-a-time?).  Indentation is something i can
always customize if i really want anyway, so i don't really
care that much.
EB@MIT-AI 02/17/82 17:48:53

I vote to keep the special IF indentation, though at first I thought
it was ugly.
BAK@MIT-AI 02/18/82 17:06:21

I am DEFINITELY against it.  I don't see the point of having the the
and else clauses go to different places.