lispとrubyとpythonと その3 リスト(lisp)

lisp編。
標準だと弱いのでseriesを追加しよう・・・としてまだかけてない。

;;リスト

;;リストを変数に設定
(setf a '(a b c d e))

;;リストの最初と「最初を除いた残り」の取得
(format t "~A~%" (car a))

(format t "~A~%" (cdr a))

;;リストの先頭にデータ追加
(format t "~A~%" (cons 'z a))

;;リストにリストを追加
(format t "~A~%" (append a '(x y z)))

;;consもappendも引数自身は書き換えない
;;なのでaは(A B C D E)のまま
(format t "~A~%" a)

;;データの取り出し
(format t "~A~%" (nth 3 a))

;;元データを更新したらどうなる??
(setf b (cons 'z a))
(setf c (append a '(x y z)))
(setf d (append '(x y z) '(g h q) a))

(setf (nth 2 a) 'update!!)

(format t "~A~%" a)
(format t "~A~%" b)
(format t "~A~%" c)
(format t "~A~%" d)

;;result
;;appendは最後の引数だったときだけ影響あり
;; (A B UPDATE!! D E)
;; (Z A B UPDATE!! D E)
;; (A B C D E X Y Z)
;; (X Y Z G H Q A B UPDATE!! D E)

(setf a '(a b c d e))

;;データの更新
(setf (nth 2 a) 'update!!)
(format t "~A~%" a)

(setf a '(a b c d e))

;;データ削除
(format t "~A~%" (remove 'c a))

;;removeも副作用はない
(format t "~A~%" a)

;;検索
(format t "~A~%" (member 'b a))

;;common lispでは
;;シーケンス+→リスト
;;          +→ベクタ(string)
;;なのでシーケンス操作関数はリストにも使える

(setf a '(a b c d e))

;;データの取り出し
(format t "~A~%" (elt a 3))

;;検索
(format t "~A~%" (find 'b a))

;;配列
;;2 × 3の二次元配列
(setf arr (make-array '(2 3) :initial-element nil))

(do ((i 0 (1+ i)))
    ((= i 2) 'DONE)
  (do ((j 0 (1+ j)))
      ((= j 3) 'DONE)
    (setf (aref arr i j) (format nil "~A-~A" i j))))

(format t "~A~%" arr)

;;データ取り出し
(format t "~A~%" (aref arr 1 2))

;;データ書き込み
(setf (aref arr 1 2) "update")
(format t "~A~%" (aref arr 1 2))

;;リテラル表記こう書いてもいい
(setf arr #2a(("0-0" "0-1" "0-2") ("1-0" "1-1" "1-2")))
(format t "~A~%" (aref arr 1 2))

(format t "~A~%" arr)

;;一次元配列=Vector
;;この3つは全部同じ意味
(setf vec (make-array 3 :initial-element nil))
(format t "~A~%" vec)
(setf vec (vector nil nil nil))
(format t "~A~%" vec)
(setf vec #(nil nil nil))
(format t "~A~%" vec)

(do ((i 0 (1+ i)))
    ((= 3 i) 'DONE)
  (setf (svref vec i) (format nil "~A" i)))

;;Vecotr用のアクセス関数
(format t "~A~%" (svref vec 2))

(setf a '(a b c d e))
(setf arr #2a(("0-0" "0-1" "0-2") ("1-0" "1-1" "1-2")))
(setf vec #("1" "2" "3"))

;;長さをとる
(format t "~A~%" (length a))
(format t "~A~%" (length vec))

;;削除
(format t "~A~%" (remove 'c a))
(format t "~A~%" (remove "2" vec :test #'equal))

;;位置の検索
(format t "~A~%" (position 'c a))
(format t "~A~%" (position "2" vec :test #'equal))

;;部分を取得
(format t "~A~%" (subseq a 3))
(format t "~A~%" (subseq vec 2))

;;ひっくりかえす
(format t "~A~%" (reverse a))
(format t "~A~%" (reverse vec))

;;ソート
;;ソートは破壊的な操作を行うので注意
(format t "~A~%" (sort '(3 4 1 2 5) #'<))
(format t "~A~%" (sort #(2 1 3) #'<))

;;全ての要素が条件を満たしているか?
(format t "~A~%" (every #'oddp '(1 3 5 7)))
(format t "~A~%" (every #'oddp #(1 3 5 7)))


;;ひとつでも要素が条件を満たしているものがあるか?
(format t "~A~%" (some #'oddp '(1 2 3 5 7)))
(format t "~A~%" (some #'oddp #(1 2 3 5 7)))

;;map系
;;リストのcarが引数にくる
(pprint (mapcar #'(lambda (e)
      (pprint e)
      (1+ e))
  '(1 2 3 4 5)))

;;戻り値がいらないときはmapc
(pprint (mapc #'(lambda (e)
    (pprint e))
       '(1 2 3 4 5)))

;;リストのcdrが引数にくる
(pprint (maplist #'(lambda (e)
      (pprint e)
      (format nil "@~A" e))
  '(1 2 3 4 5)))

;;戻り値がいらないときはmapl
(pprint (mapl #'(lambda (e)
      (pprint e)
      (format nil "@~A" e))
  '(1 2 3 4 5)))
  
;;reduceも載せとく
(pprint (reduce #'(lambda (a e)
      (+ a e))
  '(1 2 3)
  :initial-value 0))

;;和集合
(pprint (union '(1 2 3) '(3 4 5)))

;;差集合
(pprint (set-difference '(1 2 3) '(3 4 5)))

;;積集合
(pprint (intersection '(1 2 3) '(3 4 5)))

;;alist
(setf alst '((a foo) (b boo) (c woo)))

(pprint alst)
;;キーで取り出し
(pprint (assoc 'b alst))

;;hash-table
(setf ht (make-hash-table :test #'equal))

;;値の設定
(setf (gethash "a" ht) "data1")

;;値の取得
(pprint (gethash "a" ht))

;;削除
(remhash "a" ht)

(pprint (gethash "a" ht))


(setf (gethash "a" ht) "data1")
(setf (gethash "b" ht) "data2")
(setf (gethash "c" ht) "data3")
(setf (gethash "d" ht) "data4")
(setf (gethash "e" ht) "data5")

;;hashtableのMAP
;;戻り値はnil
;;mapcとかmaplと同じ感じ
(maphash #'(lambda (k v)
      (pprint (format nil "key:~A value:~A~%" k v)))
  ht)

;;構造体(わすれてた)
;;基本
(defstruct pair
  x
  y)

(setf p (make-pair))

;;値設定
(setf (pair-x p) 'a)
(setf (pair-y p) 'b)

;;値取得
(pprint (pair-x p))
(pprint (pair-y p))

(pprint p)

;;型判定
(pprint (pair-p p))

;;フィールドをキーワード引数で初期化
(setf p (make-pair :x "aaa" :y "bbb"))
(pprint p)

;;フィールドのデフォルト値を指定
(defstruct aaa 
  (aaa "aaa")
  (bbb "bbb"))

(setf a (make-aaa))
(pprint a)

;;表示方法の指定
(defun bbb-tos (p strm depth)
     (format strm "#<~A ~A>" (bbb-x p) (bbb-y p)))

(defstruct (bbb (:print-function bbb-tos))
  x
  y)

(setf b (make-bbb))
(setf (bbb-x b) "a")
(setf (bbb-y b) "b")

(pprint b)

;;アクセス関数のプレフィクス指定
(defstruct (ccc (:conc-name c))
  x
  y)

(setf c (make-ccc))

(setf (cx c) "a")
(setf (cy c) "b")

(pprint c)

;;リテラル表記
(setf c2 #S(CCC :x "aaa" :y "bbb"))
(format t "~A~%" c2)

;;やっぱり標準だと弱い
;;ジェネレータを通してないからメモリ効率が悪い?