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

ClojureでL-99 (P21 指定した位置に要素を挿入する)

| 06:42 | ClojureでL-99 (P21 指定した位置に要素を挿入する) - わだばLisperになる を含むブックマーク はてなブックマーク - ClojureでL-99 (P21 指定した位置に要素を挿入する) - わだばLisperになる

前回と同じく無限リストを利用してみました。あとおまけで、EmacsのC-tのような操作でくるくるひっくり返してゆくパターンを思い付いたので書いてみました。

とりあえず、condの節の括弧はやっぱりあった方が良いと思うんですよねー。

(defn
  #^{:doc "P21 (*) Insert an element at a given position into a list."
     :test (do (test= (insert-at 'alfa '(a b c d) 2)
                      '(a alfa b c d))
               (test= (insert-at 'alfa [] 2)
                       '(alfa))        
               (test= (insert-at 'alfa '(a b c d) -2)
                      '(alfa a b c d))
               (test= (insert-at 'alfa '(a b c d) 100)
                      '(a b c d alfa))) }
; ---------
  insert-at
; ---------
  ([item coll pos]
     (let [len (count coll)]
       (cond 
        (empty? coll) 
        (list item)
        ;; 
        (>= 0 pos) 
        (cons item coll)
        ;; 
        (<= len pos) 
        (concat coll (list item))
        ;; 
        :else 
        (mapcat #(if (= pos %1) 
                   (list item %2)
                   (list %2))
                (from 1)
                coll)))))

;; 要素をくるくるひっくり返しつつ送ってゆくパターン
(defn insert-at
  ([item coll pos]
     (loop [coll (cons item coll), cnt pos, acc [] ]
       (if (or (>= 1 cnt) (nil? (rest coll)))
         (concat (reverse acc) coll)
         (recur (cons (first coll) (rrest coll))
                (+ -1 cnt)
                (cons (second coll) acc))))))