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 |

2008-04-08

CLで学ぶ「プログラミングGauche」 (4)

| 03:25 | CLで学ぶ「プログラミングGauche」 (4) - わだばLisperになる を含むブックマーク はてなブックマーク - CLで学ぶ「プログラミングGauche」 (4) - わだばLisperになる

すっかり間があいてしまいました。

今回は4章「Gaucheの開発スタイル」です。

4.1 インタラクティブな実行とREPL

4.1.1 リテラル

このセクションに関しては大体CLも同じですが、複素数の表記方法等ちょっとした違いもあります。

それと、文字のエンコーディングについては実装依存になっているので、処理系ごとに確認する必要がありますが、大体は、external-formatで指定することになるようです。

に詳しく纏められています。

;; 浮動小数点数
3.14

;; 有理数
2/3

;; 複素数
#C(3 4)

;; 真(nil以外のすべて)
t

;; 偽
nil

;; 文字
#\a

;; 日本語 (実装依存)
#\あ
#\HIRAGANA_LETTER_A

;; SBCLでの例
sb-impl::*default-external-format*
=> :utf-8

(code-char 12354)
=> #\HIRAGANA_LETTER_A
(princ (code-char 12354))
>>> あ

;; CLISP、SBCL、Clozure CLでは#\u3042とった表記が可能
(princ #\u3042)
>>> あ

;; 制御文字等
#\Space

#\Newline

;; 文字列
"abc"
4.1.2 手続き呼び出し

このセクションもSchemeのdefineとCLのdefunは意味が違っていること以外は大体共通です。

CLのdefunは、名前に関数の実体を束縛する以外にも色々なことを行っていて、この辺は、LISP-1と、LISP-2とで違いがあります。

;; Scheme: (define sqrt2 (sqrt 2))

(setq sqrt2 (sqrt 2))
;; もしくは
(defparameter sqrt2 (sqrt 2))
(defvar sqrt2 (sqrt 2))
;; 等色々状況によって使い分けが必要

;; 手続きの定義
(defun pythagoras (x y)
  (sqrt (+ (* x x) (* y y))))

(pythagoras 3 4)
=> 5

;; (exit)
;; 大体cl-userで定義されていることが多い。
;; quitだったり、exitだったり処理系によって違う。

4.2 Emacs

ここでLispマシンの話がでてきますが、EmacsのS式操作/開発環境はLispマシンから引き継いだ操作というよりは、最初の1970年代後半のITS EMACSで完成していて、ZMACSは、もちろんEMACSの影響を受けているので、ITS EMACS→ZMACSではなかったかなと思います。ただ同時期なのではっきりしたことは言えません。…非常にどうでも良いことで誰も興味ないと思いますが、敢えて喰いついてみました(笑)

実際のところ、表4-2の快適な移動コマンドの例とC-M-\は30年以上前のオリジナルEMACSに既に全部あるので、もしかしたら、EMACSより前のエディタマクロ集の時点で既に定番だったのかもしれません。また、GNU Emacsのinferior lispモードくらいの開発環境は、PDP-10上でEMACSとMacLISPが連携するLEDITで既に実現していました。

EMACS上のCLの開発環境といえば、最近では、SLIMEが有名ですが、この章で解説されていることは殆どカバーしています。

SLIMEが便利なところとして思い付くところでは、

  • キー操作一つで式ごとコンパイルできる
  • M-.で定義したソースファイルに飛ぶことができる。これは処理系がサポートしていれば、なのですが、Allegro Cl、SBCL、Clozure CLはサポートしています。詳しくは、404 Not Foundに纏められています。ちなみに、この機能は、30年前のMIT CADR Lispマシンに既に存在します。
  • コンパイルしてエラーになったところを色付き下線で表示してくれて、M-p等で該当個所に飛べる(警告とエラーで色が別)
  • シンボル/関数を補完してくれる(補完方式には、色々あってd-bi→destructuring-bindというものや、dbind→destructuring-bind等あり)
  • 関数等のドキュメント文字列を呼び出して綺麗に表示
  • 調べたいシンボルにカーソルを合せてキー操作一つでHyperSpecが引ける
  • 自動で編集しているファイルのパッケージを認識してくれ、パッケージを移動してくれる。
  • カーソル位置のマクロの展開を行なってくれる(マクロ展開表示の上でさらにc-c c-m可能)(再帰的に最終形態まで一度に展開することも可能)
  • 調べたい関数のシンボルにカーソルを合せてキー操作一つでdisassembleの結果を表示してくれる。
  • Emacsや、Xyzzyの*scratch*バッファのように、式を評価すると結果が挿入されるようなモードがある
  • サーバ/クライアント方式なので、同一イメージに複数人が接続して開発することが可能。

等々。

このうちで、自分が気に入っているのは、マクロの展開表示です。

文章で書くと便利そうでもないかもしれませんが、

(do ((i 0 (1+ i)))
    ((= 10 i) 'end)
  (print i))

というマクロがあったとすると、カーソルを式の先頭にもっていってキーを操作すれば、

(BLOCK NIL
  (LET ((I 0))
    (TAGBODY (GO #:G1)
     #:G0    (TAGBODY (PRINT I))
             (PSETQ I (1+ I))
     #:G1    (UNLESS (= 10 I) (GO #:G0)))
    'END))

と別窓で表示してくれるという機能です。さらに、別窓の式も芋蔓式にマクロ展開できます。

この機能は非常に便利だと思うのですが、LISP使いの方と話しても、そんなのREPLで

(macroexpand-1 
 '(do ((i 0 (1+ i)))
     ((= 10 i) 'end)
   (print i)))

ってすれば良いんだよ、とか言われてしまい、便利だと思われないことが多いです。

なんでなんだー!?。まあ、自分の説明が悪いのかもしれません。

という感じで、5章に続きます。