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-10-28

mapfでonce-only

| 09:34 | mapfでonce-only - わだばLisperになる を含むブックマーク はてなブックマーク - mapfでonce-only - わだばLisperになる

ひょっとして実はmapfならonce-onlyみたいなのは綺麗に書けるんじゃないのか?と思ったので書いてみましたが、別に綺麗に書ける訳ではないようです…。というかloop以上に読み難いかもという。

(defmacro once-only ((&rest vars) &body body)
  (mapf (lambda (&rest arg)
          `(let ,(mapcar #'first arg)
             (with-gensyms ,(mapcar #'second arg)
               `(let (,,@(mapcar #'third arg))
                  ,,@body))))
        (lambda (v &aux (g (gensym)))
          `((,g ,v) ,v `(,,v ,,g)))
        vars))

;; with-gensymsも使わない版
(defmacro once-only ((&rest vars) &body body)
  (mapf (lambda (&rest arg)
          `(let ,(mapcar #'first arg)
             (let ,(mapcar (lambda (x) `(,(second x) (gensym))) arg)
               `(let (,,@(mapcar #'third arg))
                  ,,@body))))
        (lambda (v &aux (g (gensym)))
          `((,g ,v) ,v `(,,v ,,g)))
        vars))

;; 動作
(once-only (a b c)
  `(list ,a ,b ,c))
;->
(LET ((#:G2788 A) (#:G2789 B) (#:G2790 C))
  (LET ((A (GENSYM)) (B (GENSYM)) (C (GENSYM)))
    `(LET ((,A ,#:G2788) (,B ,#:G2789) (,C ,#:G2790))
       (LIST ,A ,B ,C))))

GOOでL-99 (P22 指定した範囲の数列のリスト)

| 00:15 | GOOでL-99 (P22 指定した範囲の数列のリスト) - わだばLisperになる を含むブックマーク はてなブックマーク - GOOでL-99 (P22 指定した範囲の数列のリスト) - わだばLisperになる

久々にGOOをひっぱり出してきてみました。何に由来するのか分かりませんが、GOOの作法はひどく覚えにくいと感じます。

多分、命名規則が、他のLISP方言と違うところにあるのではないかと思うのですが、この違いというのが、はっきりくっきり違うというのではなくて、微妙に違うというところが逆に覚えづらい気がします。あと関数名を短くしすぎなのも微妙に覚えづらい。あと引数の順番とか、微妙に逆。そしてマニュアルも微妙に独自。

今回は、総称関数にする必要もないので、関数です。define-functionの略のdfを使用。

(df my-range (start|<num> end|<num> by|... => <seq>)
  (def ans (packer-fab <lst>))
  (def by (if (empty? by) 1 (1st by)))
  (def r (if (<= start end)
             (range-by start <= end (op + _ by))
             (range-by start > end (op - _ by))))
  (for ((x r)) (pack-in ans x))
  (packer-res ans))

(my-range 4 9)
;=> (4 5 6 7 8 9))
(my-range 9 4)
;=> (9 8 7 6 5 4)
(my-range 3 3)
;=> '(3)

ゲスト



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