2008/07/12

[Common Lisp] 第7回 慢性的CL勉強会@Lingr 8時だョ!全員集合 のお題 The Common Lisp Cookbook - The Loop Macro を SERIES で

第7回 慢性的CL勉強会@Lingr 8時だョ!全員集合 のお題 The Common Lisp Cookbook - The Loop Macro を SERIES で。

サンプルコードによるSERIES入門 (番外編) は素晴しい。SERIES もっとはやるといいな。

;;;; The Common Lisp Cookbook - The Loop Macro
;;;; (http://cl-cookbook.sourceforge.net/loop.html)
;;;; を SERIES でやってみる。
;;;;
;;;; マニュアルはソースにくっついてくる s-doc.txt

(eval-when (:compile-toplevel :load-toplevel :execute)
(require :series))

(in-package :series)

;; #Z, #M を使えるようにする。
(eval-when (:compile-toplevel :load-toplevel :execute)
(install))

;;; a〜e を print する。
(#Mprint #z(a b c d e))
;; #Z(A B C D E)
;;; #M... は (map-fn t #'... と同じ。
(map-fn t #'print #z(a b c d e))
;; #Z(A B C D E)


;;; 2つのシリーズを1つに
(#Mlist #z(a b c d e) #z(1 2 3 4 5))
;; #Z((A 1) (B 2) (C 3) (D 4) (E 5))


;;; 1〜5 のシリーズをつくって、2倍する。
(mapping ((i (scan-range :from 1 :upto 5)))
(* 2 i))
;; #Z(2 4 6 8 10)


;;; 条件は普通に書ける。iterate は副作用を目的とする場合に。
(iterate ((x #z(a b c d e))
(y (scan-range :from 1)))
(when (> y 1)
(format t ", "))
(format t "~A" x))
;; A, B, C, D, E
;; NIL


;;; (scan-range :from 1) は無限だけど #z(a b c d e) の方で停止する。
(iterate ((x #z(a b c d e))
(y (scan-range :from 1)))
(if (> y 1)
(format t ", ~A" x)
(format t "~A" x)))
;; A, B, C, D, E
;; NIL


;;; until で停止させる。
(let* ((s #z(a b c d e 1 2 3 4))
(b (#Mnumberp s)))
(mapping ((x (until b s)))
(list x 'foo)))
;; #Z((A FOO) (B FOO) (C FOO) (D FOO) (E FOO))


;;; これも until で停止
(let* ((x (scan-range :from 1))
(y (#M(lambda (x) (* x 10)) x))
(b (#M(lambda (y) (>= y 100)) y)))
(mapping ((x x) (y (until b y)))
(print (* x 5))
y))
;; #Z(10 20 30 40 50 60 70 80 90)


;;; 二重ループ
(#M(lambda (x) (scan-range :from 1 :upto x))
(scan-range :from 1 :upto 10))
;; #Z(#Z(1) #Z(1 2) #Z(1 2 3) #Z(1 2 3 4) #Z(1 2 3 4 5) #Z(1 2 3 4 5 6) #Z(1 2 3 4 5 6 7) #Z(1 2 3 4 5 6 7 8) #Z(1 2 3 4 5 6 7 8 9) #Z(1 2 3 4 5 6 7 8 9 10))


;;; destructuring-bind したいのだけど。。。
;; なんかいい手はないかな?
(mapping ((x #z((x 1) (y 2) (z 3))))
(list (cadr x) (car x)))
;; #Z((1 X) (2 Y) (3 Z))


;;; 苦しい。previous がないと #\a がかえっちゃう。
(let ((s (scan "alpha45")))
(collect-last
(until
(previous (#M(lambda (ch)
(find ch "0123456789" :test #'eql))
s) nil)
s)))
;; #\4


;;; 1つでも真があれば
(collect-or (#Mnumberp #z(foo 2)))
;; T


;;; 1つも真でなければ
;; not をかますしかないのかな?
(collect-and (#Mnot (#Mnumberp #z(foo 2))))
;; NIL


;;; 全て真なら
(collect-and (#Mnumberp #z(foo 2)))
;; NIL

1 件のコメント:

匿名 さんのコメント...

Who knows where to download XRumer 5.0 Palladium?
Help, please. All recommend this program to effectively advertise on the Internet, this is the best program!