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 |

2009-01-28

みんなでLISPを勉強するブログ

| 23:42 | みんなでLISPを勉強するブログ - わだばLisperになる を含むブックマーク はてなブックマーク - みんなでLISPを勉強するブログ - わだばLisperになる

今日いつもの如くブログを巡回していて「LISPをみんなで勉強しよう!」というブログを始めました - @kyanny's blog経由でLISPをみんなで勉強しよう!という学習をメインにしたブログが始まったことを知りました。

このブログは、livedoorブログのグループ機能を使ったものとのことですが、はてなグループと違うのは、一つのブログを複数の人で書くというところ。

面白そうなので早速参加させてもらうことにしました。

自分は一発ネタや共有したら便利そうな情報を更新して行きたいと思っています。

2009-01-26

第31回慢性的CL勉強会 30回を振り返える

| 23:16 | 第31回慢性的CL勉強会 30回を振り返える - わだばLisperになる を含むブックマーク はてなブックマーク - 第31回慢性的CL勉強会 30回を振り返える - わだばLisperになる

今回31回目をもってCL勉強会は終了としますが、31回目はCL勉強会の30回を振り返ってみたいと思います。

31回というのは非常に中途半端だなと思ったんですが、最初はオフラインなのでオンラインでの開催は、丁度30回になりました。

これまでのお題を列挙すると下記のようになります。

  1. SLIME勉強会(オフライン)
  2. 「Tutorial on Good Lisp Programming Style」(日本語訳:良いLispプログラミングスタイル)
  3. The Power of LISP Macros / Common Lispのコンディションシステム / Lispマシン入門
  4. Common Lispのコンディションシステム(続き) / The Power of LISP Macros(続き) / CLの落し穴
  5. The Power of Lisp Macros (続き) / CLの落し穴(続き)
  6. CLの落し穴 (続き)
  7. cl-cookbook LOOPマクロ
  8. CLの落し穴 "potential numbers"から
  9. cl-cookbook 文字列篇
  10. CLの落し穴 "Limits."から
  11. cl-cookbook 日時と時刻篇
  12. CLの落し穴 パッケージ篇〜CLOS
  13. cl-cookbook ハッシュ篇 パターンマッチ/正規表現篇
  14. cl-cookbook 関数篇 / I/O篇
  15. cl-cookbook ファイル篇 / パッケージ篇
  16. cl-cookbook マクロ
  17. 参加者の環境構築状況を報告し合う
  18. 「CLでのパーシステンス」(akaさん)
  19. Let Over Lambdaを読む 1-2
  20. Let Over Lambda 2-3 /「Common Lisp 永続化入門」(onjoさん)
  21. 永続化第2弾 cl-prevalence(onjoさん)
  22. 今週のCL的活動報告(CL家族会議)
  23. どう書くorgを眺める
  24. Metatilitiesを眺める
  25. PCLを読む 1章
  26. PCLを読む 2章
  27. PCLを読む 3章
  28. PCLを読む 3章
  29. PCLを読む 4章 / LispM cadrで遊ぶ
  30. PCLを読む 5章
  31. 30回を振り返る

眺めてみると、割と色々やりました。さすがに最初は気合いが入っていますが、後半は割と力尽きてしまった感があります(笑)

自分が勉強になったなという印象が強いのは、最初のSLIME勉強会、CLの落し穴、一連の永続化入門あたりでしょうか。

永続化については、自分はあまり身近に使ってないので未だ活用できてないのですが、SLIMEと落し穴の知識については結構役に立っている気がします。

チャットとブログと

30回を通して、色々と反省点や思うところは多いのですが、リアルタイムのコミュニケーションがないのであれば、ブログ記事にしてしまった方が良いのではないかというところもありました。原稿を用意して進行をしてそれでリアルタイムで反応がないのであれば、恐らく準備の手間と後で資料として後で参照できることを考えると非常に非効率かもしれません。

特に「〜を読む」系のものはチャットで展開するのは効率が非常に悪いと感じました。とはいえ、CL勉強会では殆どそういうものばかりだったのですが(笑)

難しくて反応できなかった等の意見が聞かれることもあり、こういう場合はやはり発言も少ないのですが、こういう場合は、お題の選択としてブログに纏めて発表した方が良かったということかもしれません。

ブログでの展開の方法としては、「〜を読む」系のものは、はてなグループのようにグループを作ってみたり、事前に当事者間で相談してブログ間で密にトラックバックしあう等の方法も取れるのではないかと思いました。勉強用ブログとしてなにか新しい方法があるかもしれません。

心得的なもの

リアルタイムのチャット形式での勉強会30回を通して感じたなんとなくのの開催/参加心得的なものも書いてみようかと思います。自分は殆ど開催側でしたが、参加者側にまわったこともありますので両方から書いてみたいと思います。

  • 開催側 - 約束を守る

当然ではありますが、遅刻をしない、資料はちゃんと準備する等々、常識的なところから、期待を裏切らない的ななところまで約束を守るのが大切かなと思いました。

  • 参加者側 - 積極的に参加する

ブログを眺めてるだけなら、特にどうでも良いことですが、リアルタイムのチャットなので積極的に参加したいところです。

ROM大歓迎!とか書いておいてなんなのですが、ROMなのですから後でログを読めば良いことですし、ROMは禁止にした方が良かったかなあとも思えました(笑)

それと、「ながら」で参加も自重した方が良いかもしれません、ながらで参加する人が多くなると、レスのタイミングがどんどん遅れてきて、なんとも不思議なgdgd感が醸し出されます。まあ、私も参加者の時には、議論の最中でも途中でジュースを買いに外出したりしてたのですが(笑)。

1分間レスが続かなかったら、即撤収とか、参加者5人以下で即解散とか、そういうノリでバッサリけじめを付けるとメリハリが出て良いかもしれないです。

ということで勉強会という感じではあまりない31回目ですが、これまでの勉強会で質問できなかったことや、今後のオン/オフラインでの勉強会の展開等ご興味のある方は参加してみて頂ければと思います。

2009-01-25

第30回慢性的CL勉強会@Lingr8時だョ!全員集合まとめ

| 13:39 | 第30回慢性的CL勉強会@Lingr8時だョ!全員集合まとめ - わだばLisperになる を含むブックマーク はてなブックマーク - 第30回慢性的CL勉強会@Lingr8時だョ!全員集合まとめ - わだばLisperになる

1/24 20:00から30回目の勉強会を開催させて頂きました!

発言して頂いた方約5名、observer(ROM)の方約3名前後で、大体8名前後を推移しつつでした。

今回は、実践Common Lispを読む/5章でした。

反省点

まったり進行で約1時間で1章でしたが、普段は、さらっと流してしまうようなことでも割と細部にこだわって読むと色々あるものだなというところでした。

ログ:

謝辞:

ページへの勉強会のロゴ設置ありがとうございます!

今回も勉強会の一員に加えて頂いてありがとうございます!

2009-01-21

demoプログラム起動篇

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

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

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

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

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

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

トップレベルのsetq問題

| 12:11 | トップレベルのsetq問題 - わだばLisperになる を含むブックマーク はてなブックマーク - トップレベルのsetq問題 - わだばLisperになる

3、4ヶ月前にCL勉強会でトップレベルでのsetq問題について議論があったのですが、Richard Gabriel氏と、Kent Pitman氏のFunction Cells and Value Cellsを読んでいて興味深いことが書いてあったので自分なりに考えてみました。

興味深いのは、

17. Global Variables, Special Variables, and Constants.

の個所で、

A free variable in Common Lisp is currently taken
to be a dynamic rather than a lexical reference
because there is no global lexical environment in Common Lisp.
We introduce the concept of global variables;
when a variable is global, free references to it
are to the value cell of the symbol named by
the variable, and all bindings of it are still lexical.

のあたりです。

  • CLでは、基本的に自由変数は、レキシカル変数ではなくて、ダイナミック変数(スペシャル変数)になる
  • CLにはグローバルなレキシカル環境がない→トップレベルは空レキシカル環境
  • グローバル変数は、変数セルへの参照とする。

ということなので、これを元にトップレベルで宣言なしにsetqした場合を考えると

  • とりあえず、グローバル変数ということで変数セルに値が格納される

ということですが、今どきのSBCLや、CCLでは、トップレベルでsetqされた変数は、(symbol-value)にも値が格納されつつ同じ値を持つ非スペシャル変数という感じになっているようです。

この動作についてはどうも未定義動作らしいのですが、HyperSpecで探してもどこに書いてあるか自分は、探し出せていません…。

また、この文献についている年は、2001年なのですが、ANSI CLについての記述よりちょっと古い気がするので定義をHyperSpecであらためて確認する必要があると思いますが、同じくどの辺に書いてあるのか探し出せていません(^^;

ということでトップレベルで定義した変数にレキシカル変数の振舞いを求めることは確実ではないようなのですが、代替手段としては、define-symbol-macroを利用して模倣するというのが定番のようです。(define-symbol-macroで定義したシンボルはレキシカルに動作するため)

(defparameter *g* 42)
(define-symbol-macro ggg *g*)

(defvar *foo*
  (let ((ggg 30))
    (lambda () ggg)))

(cons ggg
      (let ((ggg 777))
        (list (funcall *foo*)
              ggg)))
;=> (42 30 777)

グローバル変数 = 値セルを参照

スペシャル変数 = ダイナミックに値セルを参照

レキシカル変数 = レキシカルスコープで環境を参照

グローバルなレキシカル変数 = なし(グローバルに定義される環境はない)

位に考えておけば良いのでしょうか。

どうも、変数のエクステントに加えて、LISP2特有の値セルの参照と、環境の参照の違いが加わってややこしいことになってる気がしてきましたが、文献を読んでなるほど!と思い書き始めたものの、また良く分からなくなって来たのでした(´▽`*)…。

そんなこんなのLISP2ですが、なぜか私はLISP2の方が好きです。

2009-01-20

Getting Started in *LISP (22)

| 10:46 | Getting Started in *LISP (22) - わだばLisperになる を含むブックマーク はてなブックマーク - Getting Started in *LISP (22) - わだばLisperになる

のんびりと続けております、*LISP入門。今回は、3.6.4からです。

3.6.4 Default and Current VP Sets

前回定義したVP setsをどうやって使うかということになるのですが、実際のところこれまでもデフォルトのVP setsを使ってきたとのこと。

初期化時に*cold-bootでサイズを指定していましたが、デフォルトのVP setsのサイズを指定していたということになります。

3.6.5 Selecting VP sets

ということで自前で定義したVP setsを利用する方法ですが、with-系マクロの*with-vp-set等を利用します。

(in-package :*lisp)

;;; 128 x 128に設定
(*cold-boot :initial-dimensions '(128 128))

現在の状況(デフォルト)を表示

(list *current-cm-configuration*
      *number-of-processors-limit*)
((128 128) 16384)

VP sets big-squareと、another-square-pvarを定義

(def-vp-set big-square '(256 256)
  :*defvars '((big-square-pvar 1)
              (another-square-pvar (random!! 20))))

*with-vp-setでbig-squareを選択

(*with-vp-set big-square
  (list *current-cm-configuration*
        *number-of-processors-limit*))
;=> ((256 256) 65536)

(list *current-cm-configuration*
      *number-of-processors-limit*)
;=> ((128 128) 16384)

*with-vp-setの外では元の設定であることが分かる。

カレントのVP setsを変更してしまいたいときは、set-vp-setを利用

(set-vp-set big-square)
;=> #<VP-SET Name: BIG-SQUARE, Dimensions (256 256), Geometry-id: 3>

(list *current-cm-configuration*
      *number-of-processors-limit*)
;=> ((256 256) 65536)

変更されたことが分かる

次回、3.6.6から再開です。

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にページを作って動画を置いています。

第29回慢性的CL勉強会@Lingr8時だョ!全員集合まとめ

| 22:02 | 第29回慢性的CL勉強会@Lingr8時だョ!全員集合まとめ - わだばLisperになる を含むブックマーク はてなブックマーク - 第29回慢性的CL勉強会@Lingr8時だョ!全員集合まとめ - わだばLisperになる

1/17 20:00から29回目の勉強会を開催させて頂きました!

発言して頂いた方約5名、observer(ROM)の方約5名前後で、大体10名前後を推移しつつでした。

今回は、実践Common Lispを読む/4章とLispマシンのエミュレータで遊んでみよう、でした。

反省点

PCLの方は普通な感じで進行できましたが、Lispマシンのエミュレータの方は、チャットで展開するにはちょっと準備と環境の足並を揃える告知が不十分だったため混沌とした感じになってしまいました。

こういう場合は、動画を用意したりしないと厳しいようです。

ログ:

謝辞:

ページへの勉強会のロゴ設置ありがとうございます!

今回も勉強会の一員に加えて頂いてありがとうございます!

2009-01-17

どう書く〜#` リーダーマクロ〜 結果

15:09 | どう書く〜#` リーダーマクロ〜 結果 - わだばLisperになる を含むブックマーク はてなブックマーク - どう書く〜#` リーダーマクロ〜 結果 - わだばLisperになる

気がつけば、「どう書く〜#` リーダーマクロ〜 - わだばLisperになる - cadr group」というお題を出してから10日以上経過してしまいました。

ちょっとマニアック過ぎて誰にも興味を持ってもらえないと思ったのですが、発表からすぐにkozimaさんに解答をブログエントリにして頂けました!

ありがとうございます!

お題を出しておいてなんなんですが、このお題は自分には難しく、ネストした表現は無理で途中で座礁してしまったのですが、晒さない訳にもいかないので恥を晒しておきます(笑)

(defun car-safe (obj)
  (if (consp obj) (car obj) obj))

(let ((*readtable* (copy-readtable nil)))
  (set-macro-character #\, 
    (lambda (str char)
      (declare (ignore char))
      `(comma ,(read str nil nil T))))
  (set-dispatch-macro-character #\# #\`
    (lambda (str char arg)
      (declare (ignore arg char))
      (let ((form (read str nil nil T)))
        (let ((pos (position 'comma form :key #'car-safe)))
          (append  (list 'progn)
                   (mapcar (lambda (x)
                             (append (subseq form 0 pos) x))
                           (apply #'mapcar #'list 
                                  (mapcar #'cadr (subseq form  pos)))))))))
  (map nil #'pprint 
       (list (read-from-string "#`(print ,(1 2 3))")
             (read-from-string "#`(send stream ,(:clear-input :clear-output))")
             (read-from-string "#`(rename-file ,(\"foo\" \"bar\") ,(\"ofoo\" \"obar\"))"))))

;-> (PROGN (PRINT 1) (PRINT 2) (PRINT 3))
;   (PROGN (SEND STREAM :CLEAR-INPUT) (SEND STREAM :CLEAR-OUTPUT))
;   (PROGN (RENAME-FILE "foo" "ofoo") (RENAME-FILE "bar" "obar"))
;=>NIL

Getting Started in *LISP (21)

| 14:59 | Getting Started in *LISP (21) - わだばLisperになる を含むブックマーク はてなブックマーク - Getting Started in *LISP (21) - わだばLisperになる

淡々と続けております、*LISP入門。今回は、3.6.2からです。

3.6.2 Where Did the Extra Processors Come From?

Connection Machineでは実プロセッサの数を越えてプロセッサを指定することができるとのことで、この場合は仮想プロセッサが使われるとのこと。

仮想プロセッサはVPと呼ばれます。

実と仮想との違いを意識することはなく透過的に使えるよう自動で設定されるようになっているとのこと。ただし、仮想なので速度は違ってきます。

3.6.3 Defining Custom Configurations - VP Sets

色々なサイズのデータを扱うようになると、pvarのサイズもまたそれに応じて設定する必要がでて来ますが、これまで見たようにpvarのサイズはプロセッサの数と同じなので、これを状況に応じて変えたいということになってきます。

この要求のためには、仮想プロセッサの仕組みを利用して対応させるとのことで、def-vp-set等を利用。

(in-package :*lisp)
(*cold-boot :initial-dimensions '(64 64))

(def-vp-set big-square '(256 256))

と定義した場合、big-squareは、仮想的な256x256の二次元グリッドになります

この作成したVP setsにも値を設定できます。

;; 初期値1で埋めたグリッド
(*defvar big-square-pvar 1 nil big-square)

;; *defvar書式
;; (*defvar variable &optional initial-value documentation (vp-set '*default-vp-set*))
;; 0-19の乱数で埋めたグリッド
(*defvar another-square-pvar (random!! 20) nil big-square)

また、default-vp-setでの宣言時にまとめることも可能です。

(def-vp-set big-square ' (256 256)
  :*defvars '((big-square-pvar 1)
              (another-square-pvar (random!! 20))))

次回、3.6.4から再開

2009-01-16

CLとPOSAアーキテクチャパターン - Layers

| 10:46 | CLとPOSAアーキテクチャパターン - Layers - わだばLisperになる を含むブックマーク はてなブックマーク - CLとPOSAアーキテクチャパターン - Layers - わだばLisperになる

デザインパターンも一通り終えて(多分まだ間違った理解/解釈が多いと思いますが…)defmethodを書く頻度も減り、なんとなく寂しいのでどうにかdefmethodを書く機会が増せないかということで、GoFデザインパターン以外にOOなパターンはないのかと探してみたところ、POSAパターンというのが有名とのこと。

邦訳「ソフトウェアアーキテクチャ—ソフトウェア開発のためのパターン体系」の原書の頭文字からPOSA本と呼ばれているらしく、GoFデザインパターンより大きい枠で捉えたアーキテクチャパターンと呼ばれるもののようです。

オブジェクト倶楽部さんのところにあるPOSAアーキテクチャパターン一覧(PDF)と、八角研究所 : ページが見つかりませんでしたをを眺めつつ考えてみることにしました。

Layersパターン

ということで、POSAパターンの最初はLayersパターンのようなのですが、説明を読んだ限りではネットワーク方面でお馴染のOSI参照モデルみたいなものだろうかと思いました。

基本的に各々のレイヤは隣のレイヤとしか関係を持たせないようにして秩序を与えるという感じかと思いますが、この仕組みをCLでどう表現するか考えてみます。

一般にはクラスの継承関係で表現したりするようですが、どうもぱっとした考えが及ばないので、CLのパッケージ機能で表現してみることにしました。

具体的には、下の層の関数や変数を">"を接頭辞としてカレントパッケージで呼び出せるようにして、下の層との連携を図ってみます。

下記のdefine-layered-packageは、defpackageに加えて下のレイヤのシンボルに接頭辞">"を付けてカレントパッケージに取り込むものです。

(in-package :cl)

(defmacro define-layered-package (name &rest args)
  (let ((base (find :base args :key #'zl:car-safe)))
    (if base
        `(PROG1
           (defpackage ,name ,@(remove :base args :key #'zl:car-safe))
           (eval-when (:compile-toplevel :load-toplevel :execute)
             (do-symbols (x (find-package ,(second base)))
               (when (eq (find-package ,(second base))
                         (symbol-package x))
                 (let ((sym (intern (format nil ">~A" x) ,name)))
                   (when (fboundp x)
                     (if (macro-function x)
                         (setf (macro-function sym)
                               (macro-function x))
                         (setf (symbol-function sym) 
                               (symbol-function x))))
                   (when (boundp x)
                     (setf (symbol-value sym) (symbol-value x)))
                   (setf (symbol-plist sym) (symbol-plist x)))))))
        `(DEFPACKAGE ,name ,@args))))

(export 'define-layered-package)

;; 補助ユーティリティ
(in-package :zl)
(defun car-safe (form)
  (if (consp form)
      (car form)
      form))

試してみる

;; 第1レイヤ
(defpackage :L-1 (:use :cl))
(in-package :L-1)

(defun fib (n a1 a2)
  (if (< n 2)
      a1
      (fib (1- n)
           (+ a1 a2)
           a1)))

;; 第2レイヤ
(define-layered-package :L-2
  (:use :cl)
  (:base :L-1))

(in-package :L-2)

(defun fib (n)
  (>fib n 1 0))

(fib 100)
;=>354224848179261915075

微妙に使えるような使えないような、ぱっとしない感じですが、一応層を分けて、隣接としか関係を持たせないという秩序立てはできる気はするので良しとします。

S式Dylanの処理系

| 07:32 | S式Dylanの処理系 - わだばLisperになる を含むブックマーク はてなブックマーク - S式Dylanの処理系 - わだばLisperになる

大分前に試していてすっかり書くのを忘れていたのですが、Dylanは当初から仕様はオープンだったということもあり、登場時に各所で実験的に作成されたインタープリタがあります。

代表的なものとして、Thomasがあり、当時のScheme処理系の上で動くものでした。

現在でもソースは入手できるので頑張れば今でも動くとは思うのですが、R3RS位なので自分は良く分からず、上手く動かせないでいました。

というところで放置していたのですが、旧MacOS用にコンパイルされたものが配布されているのを発見したので早速MacOSX上のClassic環境で動かしてみたところ素直に動くので記念エントリです。

から入手できます。

(define-method fib ((n <number>))
  (cond ((< n 2) n)
        (else: (+ (fib (- n 2))
                  (fib (- n 1))))))
(fib 10)
;=> 55

(define-class <foo> (<object>)
  x
 (y init-value: 0 init-keyword: y:))

(define-class <bar> (<foo>)
 (z init-function: (method () 333)))

(bind ((foo (make <foo> y: 8)))
  ((setter x) foo 3)
  (list (x foo) (y foo)))
;=> (3 8)

(z (make <bar>))
;=> 333

という風に書いたり試したりして遊べます。

MacOSXのClassic環境自体絶滅しそうですが、興味のある方は試してみてはいかがでしょうか。

2009-01-15

TIMEもめんどくさい

| 05:39 | TIMEもめんどくさい - わだばLisperになる を含むブックマーク はてなブックマーク - TIMEもめんどくさい - わだばLisperになる

以前に、毎度DESCRIBEを書くのが面倒ということでelispを書いてみましたが、TIMEも面倒なので同じように書いてみました。

どうも最近、SLIMEslime-with-popup-bufferに変更があったみたいでフォーカスの制御を明示的にするようになったようなので前のDESCRIBEのものも修正してみました。

(fib 30)

の上でC-sh-tすると

(fib 30)

;=> 832040
----------
Timing the evaluation of (FIB 30)

User time    =        0.060
System time  =        0.000
Elapsed time =        0.063
Allocation   = 0 bytes
0 Page faults

みたいな窓が出て、qで終了。

;; Emacs lisp
(progn
  ;; time
  (defun slime-time-form ()
    (interactive)
    (let ((defun-at-point (slime-defun-at-point)))
      (slime-eval-and-time
       defun-at-point
       `(swank:eval-and-grab-output
         ,(format "(let ((*trace-output* *standard-output*))(time %s))" defun-at-point)))))
  
  (defun slime-eval-and-time (orig-form form)
    (slime-eval-async form (slime-rcurry #'slime-show-time
                                         (slime-current-package)
                                         orig-form)))
  
  (defun slime-show-time (string package orig-form)
    (slime-with-popup-buffer ("*SLIME Time*" package t t)
      (lisp-mode)
      (princ orig-form)
      (princ "\n;=> ")
      (princ (second string))
      (princ "\n----------\n")
      (princ (first string))
      (goto-char (point-min))))
  
  ;; control-shift-t
  (define-key slime-mode-map
    [(control shift ?t)] 'slime-time-form))
;; Emacs lisp
(progn
  ;; describe
  (defun slime-describe-form ()
    "(Describe) the form at point."
    (interactive)
    (slime-eval-and-describe
     `(swank:eval-and-grab-output
       ,(format "(describe %s)" (slime-defun-at-point)))))

  (defun slime-eval-and-describe (form)
    "Describe FORM in Lisp and display the result in a new buffer."
    (slime-eval-async form (slime-rcurry #'slime-show-describe
                                         (slime-current-package))))

  (defun slime-show-describe (string package)
    (slime-with-popup-buffer ("*SLIME Describe*" package t t)
      (lisp-mode)
      (princ (first string))
      (goto-char (point-min))))

  ;; control-shift-d
  (define-key slime-mode-map
    [(control shift ?d)] 'slime-describe-form))

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-12

対になるものは先に入力する派

| 19:43 | 対になるものは先に入力する派 - わだばLisperになる を含むブックマーク はてなブックマーク - 対になるものは先に入力する派 - わだばLisperになる

自分は、()や、[]、""等は先に入力する派で、M-(やM-[、M-"等に割り当てて入力しています。(※まだpareditは使うには至っていません)

M-)も愛用しているのですが、文字列の中でM-)すると上手く動いてくれません。

これが結構不満でLispマシンだと上手く動くだけにEmacsでもZmacs風に文字列の中でもM-)が効くようにしたいところです。

ということで原因を探ることにしてみました。

M-)はmove-past-close-and-reindentという関数なのですが、

;;!はポイント
(let ((foo "bar!")))

のようなポイント位置で実行すると上手く動きません。

原因はmove-past-close-and-reindentというよりも、その中で使われているup-listが上の"bar!"のような文字列中では上手く機能しないことが原因でした。

恐らく、""を先行入力する人はそれ程多くないのであまり問題にならないのでしょう。

ということで、up-listにadviceをかけようと思いましたが、様子見ということで、とりあえずmove-past-close-and-reindentにadviceを掛けてみることにしました。

;; EMACS
(progn
  (defadvice move-past-close-and-reindent (before mpcar-before ())
    (cond (;; "foo"のうち foo"の上にいる場合
           (not (thing-at-point 'list))
           (cond ( ;; "foo"のうち 後の"の上にいる場合
                  (= ?\" (following-char))
                  (forward-char 1))
                 (t ;; "foo"のうち fooの上にいる場合
                  (forward-sexp)
                  (forward-char 1))))
          (;; "foo"のうち 前の"の上にいる場合
           (= ?\" (following-char))
           (forward-sexp))
          (t nil)))

  (ad-activate 'move-past-close-and-reindent)
  ;; 解除
  ;(ad-deactivate 'move-past-close-and-reindent)
  )

という風にしたのですが、とりあえずは目的の動作になっています。

もっと良い方法がありましたら是非とも教えて下さい!

2009-01-11

Getting Started in *LISP (20)

| 21:11 | Getting Started in *LISP (20) - わだばLisperになる を含むブックマーク はてなブックマーク - Getting Started in *LISP (20) - わだばLisperになる

3.6 Configuration Operators

これまでpvarの扱い方をみてきたが、今度は、pvar全体の規模や形を設定する方法を学ぶとのこと。

これには *cold-boot を使用する。

3.6.1 Defining the Initial Grid Configuration - *cold-boot

64x64x64プロセッサを使用する場合は、

(*cold-boot :initial-dimensions '(64 64 64))

;=> 1 ; チュートリアルでは8192になっているが…
;  (64 64 64)

とする。

現在の設定は*current-cm-configuration*や、*number-of-processors-limit*で確認できる

*current-cm-configuration*
;=> (64 64 64)

*number-of-processors-limit*
;=> 262144

なるほど、なるほど。

チュートリアルにはシミュレータの場合は、遅くなるので8x8x8位にしておきましょうという注意書きがあるのですが、当時から20年位経過しているということもありどの辺くらいまで行けそうなのか試してみました。

0-9の値をプロセッサにランダムに割り振った後で、全体をソートします。

(*cold-boot :initial-dimensions '(100 100 100))

(time (sort!! (random!! 10) '<=!!))
;>>
;(SORT!! (RANDOM!! 10) '<=!!) took 5,060,747 microseconds (5.060747 seconds) to run 
;                    with 2 available CPU cores.
;During that period, 4,920,000 microseconds (4.920000 seconds) were spent in user mode
;                    20,000 microseconds (0.020000 seconds) were spent in system mode
;1,122,322 microseconds (1.122322 seconds) was spent in GC.
; 32,000,336 bytes of memory allocated.
; 2,523 minor page faults, 0 major page faults, 0 swaps.
;#<PVAR SORT!!-RETURN :GENERAL  *DEFAULT-VP-SET* (100 100 100)>

以上、Clozure CLですが、100万プロセッサの設定でも壊れたりはしないようです。

2009-01-10

第28回慢性的CL勉強会@Lingr8時だョ!全員集合まとめ

| 23:33 | 第28回慢性的CL勉強会@Lingr8時だョ!全員集合まとめ - わだばLisperになる を含むブックマーク はてなブックマーク - 第28回慢性的CL勉強会@Lingr8時だョ!全員集合まとめ - わだばLisperになる

1/10 20:00から28回目の勉強会を開催させて頂きました!

発言して頂いた方約3名、observer(ROM)の方約5名前後で、大体8名前後を推移しつつでした。

今回は、実践Common Lispを読む、で3.4から、3章の終わりまでを読みました。

反省点

どうにも人は集まりませんでしたが、そこそこなペースだったかなと思います。

次回は、4章から再開となります。

今後について

色々考えましたが、主に私が主催してきたオンラインでの勉強会は今月いっぱいの31回目で終了としたいと思います。

元々自分個人のモチベーションとしては、ブログ等では展開できないものを模索してみようというところがありました。

恐らくこれまでのCL勉強会で一通りできそうなことは試せたかなと思いますし、オンライン上とはいえ色々な方と交流する機会が持てたことは私個人の感想になってしまいますが、非常に有意義だったかと思います。

もちろん、Lingr CL部屋は、継続して行きますし、私が主催のオンライン勉強会は休止ですが、他の方がLingr CL部屋を使って開催することはもちろん歓迎ですので、是非とも使ってやって頂ければと思います!

ログ:

謝辞:

ページへの勉強会のロゴ設置ありがとうございます!

今回も勉強会の一員に加えて頂いてありがとうございます!

2009-01-09

Getting Started in *LISP (19)

| 22:25 | Getting Started in *LISP (19) - わだばLisperになる を含むブックマーク はてなブックマーク - Getting Started in *LISP (19) - わだばLisperになる

3.5.3から再開です。

3.5.3 Sorting Pvar Values

前回に引き続き、データを変形するオペレータで有用なものには、sort!!あるとのこと。

これはpvarの範囲に作用するsortのようなもの。

(in-package :*lisp)
(*cold-boot :initial-dimensions '(8 8))
;; 8 x 8プロセッサを利用

;; グリッドを0-9の乱数で埋める
(*defvar random-numbers (random!! 10))

;; 確認してみる
(ppp random-numbers :end 20)
;>> 1 6 5 0 5 2 9 0 0 6 8 3 9 8 5 4 0 9 5 9
;=> NIL

プロセッサ番号が20より小さい範囲にsort!!を適用。述語は<=!!なので、<=で比較されるsortのようなもの。

(*when (<!! (self-address!!) 20)
  (ppp (sort!! random-numbers '<=!!) :end 20))
;>> 0 0 0 0 1 2 3 4 5 5 5 5 6 6 8 8 9 9 9 9 
;=> NIL

ソートのルーチンを自作したい場合のために、rank!!という関数も用意されている。

これは、pvarの数値的な順位を返す。

(*when (<!! (self-address!!) 20)
  (ppp (rank!! random-numbers '<=!!) :end 20))
;;; 1  6  5 0  5 2  9 0 0  6  8 3  9  8 5 4 0  9 5  9 pvarの値
;>> 4 13 11 3 10 5 19 2 1 12 15 6 18 14 9 7 0 17 8 16
;=> NIL

この例では、値が0の8番プロセッサが1番になっていることが確認できる。

次回、3.6から再開

2009-01-07

%fooの由来

| 18:15 | %fooの由来 - わだばLisperになる を含むブックマーク はてなブックマーク - %fooの由来 - わだばLisperになる

またまたLispマシンネタなのですが、%fooの由来がLispマシンなのではないかということでネタにしてみることにしました。

%fooという関数名は、現在の慣習では内部的な関数ということを意味し、利用にも注意が必要ということが多いと思うのですが、Lispマシンでは、%fooはLISPのレベルより下のマイクロコードで組まれた関数を意味していました。

利用上の注意は恐らく同じだと思うのですが、マイクロコードで組まれていなければ、%は付かず、LISPレベルでの下請け的な関数は、foo1、foo2としていることが多いようです。(foo1は、fooのfoo2はfoo1の下請け)

2009-01-05

どう書く〜#` リーダーマクロ〜

| 20:08 | どう書く〜#` リーダーマクロ〜 - わだばLisperになる を含むブックマーク はてなブックマーク - どう書く〜#` リーダーマクロ〜 - わだばLisperになる

またまたLispマシンのマニュアルを眺めていて、変ったリーダーマクロをみつけました。

#'は、MacLISPの時代からfunctionなのですが、Lispマシンには#`の定義があったようです。

その内容なのですが、

#`(send stream ',(:clear-input :clear-output))
;>>>
(progn (send stream :clear-input)
       (send stream :clear-output))

#`(rename-file ,("foo" "bar") ,("ofoo" "obar"))
;>>>
(progn (rename-file "foo" "ofoo")
       (rename-file "bar" "obar"))

というもののようです。さらにネストできて

#`#`(print (* ,(5 7) ,,(11. 13.)))
;>>>
(progn (progn (print (* 5 11.)) (print (* 7 11.)))
       (progn (print (* 5 13.)) (print (* 7 13.))))

になるらしいです。

最初の2つは比較的簡単にできたのですが、最後の例がなんだか良く分かりません。

ということで、興味のある方は再現に挑戦してみては如何でしょうか!

ちなみに来週位に私の解答を発表してみたいと思います。

※最初の例のquoteの解釈ですが、もしかしたら誤植で、

(progn (send stream ':clear-input)
       (send stream ':clear-output))

かもしれません、TI-Explorerのエミュレータではこの様に展開されています。

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という構文)。

2009-01-04

第27回慢性的CL勉強会@Lingr8時だョ!全員集合まとめ

| 23:10 | 第27回慢性的CL勉強会@Lingr8時だョ!全員集合まとめ - わだばLisperになる を含むブックマーク はてなブックマーク - 第27回慢性的CL勉強会@Lingr8時だョ!全員集合まとめ - わだばLisperになる

1/3 20:00から27回目の勉強会を開催させて頂きました!

発言して頂いた方約4名、observer(ROM)の方約5前後で、大体9名前後を推移しつつでした。

今回は、実践Common Lispを読む、で3.3まで章を読みました。

次回は、3.4章から再開です。

反省点

三が日だけに人は集まりませんでしたが、割と良いペースだったかなと思います。

ログ:

謝辞:

ページへの勉強会のロゴ設置ありがとうございます!

今回も勉強会の一員に加えて頂いてありがとうございます!

2009-01-02

Getting Started in *LISP (18)

| 23:27 | Getting Started in *LISP (18) - わだばLisperになる を含むブックマーク はてなブックマーク - Getting Started in *LISP (18) - わだばLisperになる

今回は3.5.2から再開です。

3.5.2 Spreading Values across the Grid

スキャニングのオペレーションには他にスプレディッングがあるとのこと。

スプレディッングとは、指定した一点を列か行に押し広げることで、*Lispの場合は、2次元以上にも構成できるのでこの表現には語弊があるものの、方法論としては同じとのこと。

スプレディッングには、spread!!を利用する。

(in-package :*lisp)
;; 256 x 256プロセッサを利用
(*cold-boot :initial-dimensions '(8 8))

(ppp (self-address!!)
     :mode :grid
     :end '(8 3)
     :format "~3S ")
;>>
;       DIMENSION 0 (X)  ----->
;  
;  0   8   16  24  32  40  48  56  
;  1   9   17  25  33  41  49  57  
;  2   10  18  26  34  42  50  58  
;=>NIL

という構成のグリッドがあるとする。

この構成に(spread!! (self-address!!) 0 3)適用する。

0は0次元、3は列になり、0次元の3列目を行全体の値とすることを指示している。

(ppp (spread!! (self-address!!) 0 3) ;; Dimension 0, Coord. 3
     :mode :grid
     :end '(8 3)
     :format "~3S ")

;>>     DIMENSION 0 (X)  ----->
;  
;  24  24  24  24  24  24  24  24  
;  25  25  25  25  25  25  25  25  
;  26  26  26  26  26  26  26  26  
;=> NIL

次回、3.5.3から再開

2009-01-01

describeが面倒臭い

| 21:57 | describeが面倒臭い - わだばLisperになる を含むブックマーク はてなブックマーク - describeが面倒臭い - わだばLisperになる

最近インスタンスの中身を確認したいことが多いのですが、describeの結果を確認するためにd.e.s.c.r.i.b.eといちいちタイプするのが面倒なのでslimeの中の関数を参考にしてelispを書いてみました。

;; EMACS Lisp
(progn
  (defun slime-describe-form ()
    "(Describe) the form at point."
    (interactive)
    (slime-eval-and-describe
     `(swank:eval-and-grab-output
       ,(format "(describe %s)" (slime-defun-at-point)))))

  (defun slime-eval-and-describe (form)
    "Describe FORM in Lisp and display the result in a new buffer."
    (slime-eval-async form (slime-rcurry #'slime-show-describe
                                         (slime-current-package))))

  (defun slime-show-describe (string package)
    (slime-with-popup-buffer ("*SLIME Describe*" package)
      (princ string)
      (goto-char (point-min))))

  ;; control-shift-d
  (define-key slime-mode-map
    [(control shift ?d)] 'slime-describe-form))

使い方

(make-instance 'mime:text-mime :content "あけましておめでとう")

等のトップレベルのフォームの上で実行すると

(#<CL-MIME:TEXT-MIME {100C4FE321}>
is an instance of class #<STANDARD-CLASS CL-MIME:TEXT-MIME>.
The following slots have :INSTANCE allocation:
 CONTENT-TYPE                   "text"
 CONTENT-SUBTYPE                "plain"
 CONTENT-TYPE-PARAMETERS        NIL
 CONTENT-ID                     NIL
 CONTENT-DESCRIPTION            NIL
 CONTENT-TRANSFER-ENCODING      :7BIT
 CONTENT-ENCODING               :7BIT
 CONTENT-DISPOSITION            NIL
 CONTENT-DISPOSITION-PARAMETERS   NIL
 CONTENT                        "あけましておめでとう"
 MIME-VERSION                   "1.0"
 CHARSET                        "us-ascii"
 )

のような画面が別枠で開き、qで閉じます。

既に存在しているような気がしてならないのですが、slime-describe-symbolはあっても(describe ...)の結果を表示するものは探してもみつけられませんでした。

ということで作ってみたのですが、SLIMEでdescribeをフォームにかける方法をご存知の方は教えて下さい!