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

gensymのリスト

| 11:58 | gensymのリスト - わだばLisperになる を含むブックマーク はてなブックマーク - gensymのリスト - わだばLisperになる

当初、気の効いたイディオムを探索するという趣旨でしたが、見付けようと思ってもなかなか見付からないので、適当にイディオムを探してエントリを書くことにしました(^^;

さて、CLのマクロを書いていると、変数のリストと同じ長さのgensymのリストが欲しくなることがあると思います。

'(a b c)
;=>
(#:g000001 #:g000002 #:g000003)

そこに焦点を当てて人間模様を観察してみたいと思います。

とりあえず、

(defparameter *lst* '(foo bar baz))

としておきます。

(1)Paul Graham氏

(mapcar (lambda (x) (gensym)) *lst*)

;; コンパイラに警告されるので、ignoreする場合。
(mapcar (lambda (x) 
	  (declare (ignore x))
	  (gensym))
	*lst*)

アンチloopの人なので、mapcarで。

declareあり、45文字。なしは、31文字

(2)適当に変種。declareが長いので、valuesで2値目を捨てるぞ、という場合。

(mapcar (lambda (x) (values (gensym) x))
	*lst*)

でも、分かりにくい。42文字

(3)やっぱりloopが定番だろう

(loop :for g :in *lst* :collect (gensym))

loopがぴったり嵌まる状況な気がする。36文字。

アンチloopじゃない人は、普通にこちらかも。

(4)dolistはどうか。

(let (res)
  (dolist (g *lst* res)
    (push (gensym) res)))

見たことない。49文字

(4)Brian Mastenbrook氏(common-idiomsより)

わざわざ、fconstantlyというconstantlyに似た関数を定義して使う。

(mapcar (fconstantly #'gensym) *lst*)

fconstantlyに汎用性はあるんだろうか。基本的にこのシチュエーション専用な気が…。

fconstantlyをインポートすれば、32文字。しなければ、46文字。

まとめ

以上、色々(といっても基本的に3バージョン)纏めてみましたが、最短は、31文字で、declareなしのPG方式。警告回避の場合32文字でfconstantly

しかし、やっぱりloopが定番なのではないでしょうか。

もっと良い方法があったら教えて下さい!

ArcでL-99 (P57 二分探索木の作成)

| 10:51 | ArcでL-99 (P57 二分探索木の作成) - わだばLisperになる を含むブックマーク はてなブックマーク - ArcでL-99 (P57 二分探索木の作成) - わだばLisperになる

久々のArc。今回のお題は、数値のリストを二分探索木的に配置しましょう、というもの。

また、その結果を前回作成した、symmetric?で確認してみよう、とのことです。

(construct '(3 2 5 7 1))
;=> (3 (2 (1 nil nil) nil) (5 nil (7 nil nil)))

;; symmetric?で確認
(symmetric? (construct '(5 3 18 1 4 12 21)))
;=> t

(symmetric? (construct '(3 2 5 7 1)))
;=> nil

(def add-leaf (leaf tree)
  (with ((root left right) tree
         node `(,leaf () () ))
    (if (<= leaf root)
        (if no.left
            `(,root ,node ,right)
            `(,root ,(add-leaf leaf left) ,right))
        (if no.right
            `(,root ,left ,node)
            `(,root ,left ,(add-leaf leaf right))))))

(def construct (lst)
  (reduce (fn (lst leaf) (add-leaf leaf lst))
          (let (head . tail) lst
            (cons `(,head () () ) tail))))

COMMON LISP JP 今日投稿されたネタと質問

| 06:22 | COMMON LISP JP 今日投稿されたネタと質問 - わだばLisperになる を含むブックマーク はてなブックマーク - COMMON LISP JP 今日投稿されたネタと質問 - わだばLisperになる

毎日LingrのCL部屋に投稿されたネタを纏めてみることにしました。

といっても、殆ど私が投稿しているだけであり、激しく自作自演な状況です(笑)

良かったら質問とかしてみて下さい。

質問の場合、タイトル+内容という感じで書くと後で探しやすく、回答もしやすいかなと思っています。

話題:

5/1

  1. SLIMEの最近の変更 - debugオプションの追加
  2. stumpwm
  3. SLIMEとanything.el

5/2

  1. cl-win32oleがCodeReposへ
  2. ひげぽんさん、Lisp/SchemeのIRCチャンネル物色中
  3. Worse is better

質問

  1. LOOPマクロの質問

CLOSでL-99 (P20 指定した要素を削除)

| 05:54 | CLOSでL-99 (P20 指定した要素を削除) - わだばLisperになる を含むブックマーク はてなブックマーク - CLOSでL-99 (P20 指定した要素を削除) - わだばLisperになる

なんとなく、「面倒版」ではベクタを基本にして、他は型変換させるように書いてみましたが、色々な型に対応する関数を書くときはやっぱりリストを基本にするんでしょうか。

型変換するにもコストが掛かるだろうし、型ごとに個別に記述するのも面倒だし、落し所の判断が難しいなあ(;´Д`)

ベンチマーク取ったりして判断するのかな?

(remove-at #(1 2 3 4 5 6) 1)
;=> #(2 3 4 5 6)
(remove-at '(1 2 3 4 5 6) 1)
;=> (2 3 4 5 6)
(remove-at "123456" 1)
;=> "23456"

(defgeneric REMOVE-AT (sequence position)
  (:documentation "P20 (*) Remove the K'th element from a list."))

;; 単純版
(defmethod REMOVE-AT ((sequence sequence) (position integer))
  (concatenate (class-of sequence)
               (subseq sequence 0 (1- position)) 
               (subseq sequence position)))

;; 面倒版
(defmethod REMOVE-AT ((sequence vector) (position integer))
  (let ((len (length sequence)))
    (if (not (<= 1 position len))
        (copy-seq sequence)
        (loop :with res := (if (stringp sequence)
                               (make-string (1- len))
                               (make-array (1- len))) 
              :and ridx := 0 
              :for x :across sequence
              :for idx :from 1 :to len
              :unless (= position idx) 
                  :do (setf (aref res ridx) x) 
                      (incf ridx)
              :finally (return res)))))

(defmethod REMOVE-AT ((sequence sequence) (position integer))
  (coerce (remove-at (coerce sequence 'vector) position)
          (class-of sequence)))

ゲスト



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