loopとmaphashとiterate

http://d.hatena.ne.jp/ytakenaka/20070703/p1
Common Lispの話。
iterateも仲間に入れてくれw

値を設定

(in-package :iter)
(defvar *hash* (make-hash-table))

(loop for x from 97 to (+ 97 25)
   and y = (random 1.0)
   do
   (setf (gethash (code-char x) *hash*) y))

(iter (for x from 97 to (+ 97 25))
      (for y = (random 1.0))
      (setf (gethash (code-char x) *hash*) y))

一覧表示

(maphash #'(lambda (k v)
             (format t "~a => ~a~%" k v)) *hash*)

(loop for v being the hash-value using (hash-key k) of *hash*
              do (format t "~a => ~a~%" k v))

(iter (for (k v) in-hashtable *hash*)
      (format t "~a => ~a~%" k v))

ハッシュ値の足し算

(let ((result 0))
  (maphash #'(lambda (k v)
               (incf result v)) *hash*)
  result)

(loop for v being the hash-value of *hash* sum v)

(iter (for (k v) in-hashtable *hash*) (sum v))

機能の一般化

(defun cumulate/maphash (init-value op hash-table)
  (let ((result init-value))
    (maphash #'(lambda(k v)
                 (setf result (funcall op result v)))
             hash-table)
    result))

(defun cumulate/loop (init-value op hash-table)
  (loop for v being the hash-value of hash-table
       with result = init-value
       do
       (setf result (funcall op result v))
       finally (return result)))

(defun cumulate/iter (init-value op hash-table)
  (iter (for (k v) in-hashtable hash-table)
        (reducing v by op initial-value init-value)))

使用例

(cumulate/maphash 1 #'* *hash*)
(cumulate/loop 1 #'* *hash*)
(cumulate/iter 1 #'* *hash*)
(iter (for (k v) in-hashtable *hash*) (multiply v))

おまけ

(iter (for (k v) in-hashtable *hash*) (reducing (list (cons k v)) by #'append initial-value nil))
(iter (for (k v) in-hashtable *hash*) (collect (cons k v)))