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 |

2007-10-28

Alexandria (1)

| 01:21 | Alexandria (1) - わだばLisperになる を含むブックマーク はてなブックマーク - Alexandria (1) - わだばLisperになる

PG氏の余り物ユーティリティを読み終ったので、次は何にしようかと悩みましたが、とりあえず、定番ユーティリティ集の座を狙っているような、alexandriaのコードを読んでみることにしました。

名前からして、立派な図書館であったAlexandria図書館のようなライブラリを目指しているのであろうということは何となく分かります。

とりあえず、適当にぽつぽつと拾い読みしてみたいと思っています。

Alexandriaのページ:Alexandria

asdf-installも可能なようですが、プロジェクトの人が準備したものではないようです。

とりあえず自分は、公式ページの通りdarcsで取得して、手動でasdfに登録しました。

お題

features

暗記で再現

;--- features.lisp
(defun featurep (feature-expression)
  (etypecase feature-expression
    (symbol (not (null (member feature-expression *features*))))
    (cons   (ecase (first feature-expression)
	      (:and (every #'featurep (rest feature-expression)))
	      (:or  (some  #'featurep (rest feature-expression)))
	      (:not (not (featurep (second feature-expression))))))))

できた。carとcdrを使わないのに、cadrを使うのは謎なのでsecondにしてみた。

Emacs Lispではお馴染で、Emacs上でコードを編集しているとハイライト表示もされるしCommon Lisp標準の機能かと思いきや、標準ではなかったりするfeaturep。

後期Maclispにはあるようなので、その流れでEmacsにもあるのかもしれません。

これはCLRFIの1番で定義されているfeaturepとまったく同じコードなんですが、CLRFIとも関係あるのでしょうか。

;; 動作
(featurep :cffi)
;=> t
(featurep '(:not :cffi))
;=> nil
(featurep '(:and :sbcl :x86 :linux))
;=> t

お題

clamp

暗記で再現

;--- numbers.lisp
(declaim (inline clamp))
(defun clamp (number min max)
  (if (< number min)
      min
      (if (> number max)
	  max
	  number)))

できた。上限と下限を設定して、はみ出したものは上限か下限の値を返すというものらしい。

自分は何となく

(defun clamp (number min max)
  (cond ((< number min) min)
	((> number max) max)
	('T number)))

と書きたい派。

;; 動作
(clamp 101 1 100)
;=> 100

お題

iota

暗記で再現

;--- numbers.lisp
(declaim (inline iota))
(defun iota (n &key (start 0) (step 1))
  (declare (type (integer 0) n) (number start stop))
  (loop :repeat n 
        :for i = (+ start (- step step)) :then (+ i step)
        :collect i))

できた。これはおなじみSRFIのiota。しかし、startや、stepをキーワード引数として取るようにしているところが違う。

;; 動作
(iota 10 :start 1.5 :step 2)
;=> (1.5 3.5 5.5 7.5 9.5 11.5 13.5 15.5 17.5 19.5)

お題

map-iota

暗記で再現

;--- numbers.lisp
(declaim (inline map-iota))
(defun map-iota (n fn &key (start 0) (step 1))
  (declare (type (integer 0) n) (number start step))
  (loop :repeat n
        :for i = (+ start (- step step)) :then (+ i step)
        :do (funcall fn i))
  n)

できた。iotaの結果の各要素に関数を適用するという感じ。

PG氏のmap-intに非常に近いような気もするけれど、返り値は、結果のリストではなくて、引数のnを返したりするところが違う。

;; 動作
(map-iota #'princ 5 :start 1 :step 2)
->13579
;; 参考 PG氏のmap-int
(defun map-int (func n)
  "call FUNC on integers from 0 through N - 1, returning a list of the results."
  (let ((acc '()))
    (dotimes (i n)
      (push (funcall func i)
	    acc))
    (nreverse acc)))

雑感

今のところこのライブラリに含まれるマクロや関数の由来を記したドキュメントの類が全然ないんですが、手持ちの駒の重複を把握するためにもあると便利だなと感じました。