LISP

Ubuntu11.10でClozure CLを使うときの注意事項

Ubuntu11.10にemacs、slime、Clozure CLをインストールした時のメモ。

Chromium OSをビルドするためにUbuntu11.10の64ビット版をvaio Tにインストールした。
その環境が思いのほか快適だったので、ついでに開発環境としてClozure CLを入れたのだが、SBCLと違って少しつまづいたので、その備忘録を残しておこうと思う。

Ubuntu11.10のソフトウェアセンターからインストールできるslimeは、SBCL用の設定になっているようだ。
また、同じくソフトウェアセンターからインストールできるemacsはslimeが"/usr/share/common-lisp/source/slime"にあることを期待する設定になっている。

そこで、Clozure clを使う場合は、slimeの最新版を持ってきて、"/usr/share/common-lisp/source/slime"に置くのが簡単だ。

あとのemacsの設定は「ありえるえりあ」さんのModern Common Lispシリーズなどを参考にしていけば良いだろう。

| | コメント (0) | トラックバック (0)

Common Lispのグローバル変数

Common Lispではグローバル変数(スペシャル変数)を定義する方法が2つある。
一つはdefparameterフォームを使う方法で、もう一つはdefvarフォームを使う方法だ。

この二つの使い分けを、Lispが得意とするプロトタイピングの観点から整理してみた。
つまり、

  • ソースコードを修正しても、修正前の値が維持される変数はdefvarで定義する
  • ソースコードを修正した影響がすぐに反映される変数はdefparameterで定義する

と考える。
プロトタイピングでは、設計しながら実装とリファクタリングをしていくので、こういう場面にはよく出くわす。

今、こんなソースコードを作っているとする。

(defparameter *delta* 1)
(defvar *count* 0)

(defun increment-widget-count()
  (incf *count* *delta*))

これをコンパイルしてロードする。

CL-USER> (compile-file "/work/param.lisp")
CL-USER> (load "param")

*delta*は1だ。

CL-USER> *delta*
1

*count*は0だ。

CL-USER> *count*
0

関数を3回実行すると、countは3になる。

CL-USER> (increment-widget-count)
1
CL-USER> (increment-widget-count)
2
CL-USER> (increment-widget-count)
3

ここでソースコードの*delta*を2に修正する。

(defparameter *delta* 2)
(defvar *count* 0)

(defun increment-widget-count()
  (incf *count* *delta*))

このファイルを再コンパイルしてロードする。

CL-USER> (compile-file "/work/param.lisp")
CL-USER> (load "param")

*delta*を確認すると、修正が反映されて2になっている。

CL-USER> *delta*
2

*count*を確認すると、3のままだ。

CL-USER> *count*
3

関数を3回実行すると、countは今度は2づつ増えて9になる。

CL-USER> (increment-widget-count)
5
CL-USER> (increment-widget-count)
7
CL-USER> (increment-widget-count)
9
CL-USER> *count*
9

| | コメント (0) | トラックバック (0)

スタンダートテキスト"ANSI Common Lisp"

ピアソン・エデュケーションの"ANSI Common Lisp"は良いテキストなのだが、練習問題に正解がついていないのが、玉に瑕だ。
安易に正解に頼らない、「勉強かくあるべし」という姿勢はとても良いと思うが、難しい問題もあるのでやはり正解は欲しい。

どんな練習問題があるかというと、例えば4章の第一問は、

正方の配列(大きさが(n n)の配列)を引数としてそれを90度、時計回りに回転させる関数を定義せよ。

というもので、例として
>(quarter-turn #2A((a b) (c d)))
#2A((C A) (D B))

とある。
最初、何を言っているのか正直わからなかったが、

a b
c d

c a
d b

に、

a b c
d e f
g h i

g d a
h e b
i  f  c

に変換する関数のことらしい。
そこで、こんな解答を作ってみた。
一応動いているようだ。

(defun quarter-turn (a)
  (let ((nn (array-dimensions a)))
    (let ((n (car nn))
          (b (make-array nn)))
        (do ((i 0 (+ i 1))) ((= i n))
          (do ((j 0 (+ j 1))) ((= j n))
            (setf (aref b j (- n 1 i)) (aref a i j))))
      b)))

ANSI Common Lisp (スタンダードテキスト) Book ANSI Common Lisp (スタンダードテキスト)

著者:ポール グレアム
販売元:ピアソンエデュケーション
Amazon.co.jpで詳細を確認する

ANSI Common Lisp ANSI Common Lisp

販売元:楽天ブックス
楽天市場で詳細を確認する

| | コメント (0) | トラックバック (0)

Ubuntu10.04でのLISP環境構築

Ubuntu10.04にLISP環境を構築してみた。
今回使ったのは次の3つのソフトウェアだ。

  • SBCL
  • SLIME
  • emacs

全て、Synapticパッケージマネージャで簡単にインストールできる。
インストールした後、.emacsに下記を追加する。

; SLIME
  (setq slime-net-coding-system 'utf-8-unix)
  (setq inferior-lisp-program "/usr/bin/sbcl")
  (add-to-list 'load-path "/usr/share/emacs/site-lisp/slime")
  (require 'slime)
  (slime-setup)

1行目はLISPが日本語を使えるようにするために必要だ。
2行目から5行目までは、SLIMEのインストールガイドに書かれている通りだ。

このように環境構築はとても簡単だ。また、emacsとLISPの組合せは非常に軽快で、気持ちよくプログラミングできる。

周りにLISPを使っている人はあまりいないかもしれないが、Pythonのリスト処理や関数を気に入って使っている人なら、LISPもお気に入りの言語になるかもしれない。

WOZ

| | コメント (0) | トラックバック (0)