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

CLの開発環境/ライブラリ等の設定

| 18:01 | CLの開発環境/ライブラリ等の設定 - わだばLisperになる を含むブックマーク はてなブックマーク - CLの開発環境/ライブラリ等の設定 - わだばLisperになる

quekさんのletter: [Common Lisp] SBCL 環境 ライブラリ ~/.sbclrc

を読んで、確かにCLerの人々は、処理系をどういう設定で使っているのか、という情報は少ないなぁと思ったので、参考になるかどうかは疑問ですが、自分もどういう感じで使っているかを晒してみることにしました!

処理系

大した理由はないのですが、できるだけ沢山の処理系をできるだけ沢山のOSで動かすというのを目標にしています。

現在、SBCL、Clozure CL、Allegro CL、LispWorks、ECL、ABCL、CMUCL、MCLをMacOSX、Linuxの組み合わせで使っていて、MCL以外は、大体全部同じライブラリ環境で揃えています。ちなみにFFI系を利用するものが揃えられないのは、諦めています(^^;

ライブラリの設定

ライブラリ環境を揃えるのには、以前もこのブログで書いたasdf-addonsを利用しています。

asdf-addonsを利用すると、複数の処理系でライブラリを揃えるのが非常に楽なのでお勧めです。

他に似たものとしては、asdf-binary-locationsがあるようです。

処理系ごとの初期化ファイル

自分は、処理系ごとにSWANKが起動できて頻繁に利用するパッケージを全部読み込んだイメージをダンプしています。

イメージの作成にはmake-core.lispのような処理系で共通のファイルを作成して、各処理系が共通のライブラリを読み込んでダンプしています。

そして、作成したイメージを使ってSWANKを起動し、SLIMEで接続して利用しています。

各処理系毎の初期化ファイルは殆ど利用していませんが、Allegroの試用版だと処理系起動時にコアファイルとロードさせるファイルの両方を指定できないようなので、

.clinit.clに

;; .clinit.cl
;; -*- lisp -*-
;(princ "Hello! init file")

(and (find-package :swank)
     (load (merge-pathnames"etc/slime.lisp" (user-homedir-pathname))))

のようにして、SWANKを起動させるのに初期化ファイルを例外的に利用している位です。

まとめ

という感じで、自分は、環境をいちいちダンプしているのですが、ダンプするのもバッチ処理的なファイルを作成しておけば良いので割と頻繁にダンプしています。

イメージをダンプできないもの(LispWorksの評価版など)もあるのですが、この場合は、イメージ作成用のバッチファイルが、環境をロードするためのファイルになるようにしています。

CLで学ぶ「プログラミングGauche」 (7.7〜7.9)

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

7.7章から再開です。

7.7 省略可能引数とキーワード引数

省略可能引数とキーワード引数は、Gaucheの拡張で便利なのでCLから輸入されたとのことです。

CLでは、Gaucheと違って前回の内容でも書いたラムダリストパラメータで色々指定することになります。

可変長引数をリストとして受け取ってlet-optionals*で自前で分解する、という方法ではなく、

(defun my-make-list (num &optional args))

という風に指定することになります。

どうしても、let-optionalsが使いたいんだ!!という場合は、マクロを書くことになると思います…。

(defmacro let-optionals* ((&rest args) (&rest vars-and-inits) &body body)
  (let ((vars-and-inits (copy-list vars-and-inits)))
    `(let* ,(map-into vars-and-inits 
                      (lambda (val vi) `(,(car vi) ,val))
                      args
                      vars-and-inits)
       ,@body)))

(let-optionals* (1 2) ((a 100) (b 200) (c 300))
  (list a b c))
;=> (1 2 300)

等々。

キーワードに関しても、同じように、

(defun my-make-list (num &key (init-elt nil)))

のように指定します。

また、キーワードかどうか判定するには、keywordpを使います。

(keywordp :foo)

キーワード引数のメリットとしてはGauche本の解説の通りですが、CLの場合、:fooというのは、keywordパッケージに登録されたシンボルということになり、keyword:fooの省略形であるというところが違います。また、キーワードはnilや、tのように自己を評価した結果は自分自身になります。

ちなみに、何がなんでも、let-keywordが使いたいんだ!!という場合は、これまたマクロを書くことになると思います…。

(defmacro let-keyword (args (&rest keys-and-inits) &body body)
  (let* ((g (gensym))
         (vars-and-inits (mapcar (lambda (x) 
                                   `(,(intern (string (car x)))
                                      (or (getf ,g ,(car x)) ,(cadr x))))
                                 keys-and-inits)))
    `(let ((,g ,args))
       (let ,vars-and-inits
         ,@body))))

;; other-argsに対応するの忘れてました…。

どっちにしろ、普通に引数で指定した方が便利なので、CLを学ぼうという方は、そちらで書いて下さい(^^;

7.8 部分適用

ここでは、cutの説明がありますが、CLにはcutに相当するスタンダードなものはないと思います。

しかし、色々な試みはあって、リーダーマクロ

(mapcar #'(lambda (x) (* 2 x))
        '(1 2 3))

(mapcar #L(* 2 _) '(1 2 3))

のように書けるようにしたりしている人は多いようです。

参考:no title

また、cutマクロを作るのもそんなに難しくないと思うので自作されるのも良いかと思います。

自分は、CL版のdefine-syntaxを利用してcutを移植してみたことがありました。

define-syntaxでcut:Common Lispであんまり衛生的ではないdefine-syntax - わだばLisperになる - cadr group

7.9 多値

多値の役割についても、SchemeとCLで違いはないと思います。

7.9.1 多値を受けとる

CLでSchemeのreceiveに相当するものは、 multiple-value-bindになるかと思います。

;(defun min&max (&rest args)
;  (values (apply #'min args) (apply #'max args)))

(multiple-value-bind (min-val max-val)
    (min&max 3 1 2)
  (list min-val max-val))

;=> (1 3)

let-valuesとlet-values*に相当する標準的なものはありませんが、そういうユーティリティは沢山あると思います。

自分は、metabang-bindを良く使います。

このパッケージのbindは、destructuring-bindと、multiple-value-bindを一緒にした上に構造体もバインドできるというものです。

let-valuesだと

(bind (((:values min-val max-val) (min&max 3 1 2)))
  (list min-val max-val))

のように書けます。

value-refに相当するものとしては、nth-valueがあり

(nth-value 1 (min&max 3 1 2))
;=> 3

という風になります。

7.9.2 多値を返す

多値を返すのには、Schemeと同じくvaluesを使います。

(values 1 2 3 4)
;=> 1,2,3,4

ということで、次回は8章からです。

ゲスト



トラックバック - http://cadr.g.hatena.ne.jp/g000001/20080505