fix defmacro-driver example in manual
Fri May 25 01:14:43 PDT 2007 Joerg-Cyril Hoehle <hoehle@users.sourceforge.net>
* fix defmacro-driver example in manual
diff -rN -u old-iterate/doc/iterate.texinfo new-iterate/doc/iterate.texinfo
--- old-iterate/doc/iterate.texinfo 2014-07-28 13:33:36.000000000 -0700
+++ new-iterate/doc/iterate.texinfo 2014-07-28 13:33:36.000000000 -0700
@@ -1950,32 +1950,40 @@
@lisp
(defmacro-clause (FINDING expr MAXIMIZING func &optional INTO var)
- (let ((max-val (gensym))
- (temp1 (gensym))
- (temp2 (gensym))
+ "Simple FINDING... MAXIMIZING implementation"
+ (let ((max-val (gensym "MAX-VAL"))
+ (temp1 (gensym "EL"))
+ (temp2 (gensym "VAL"))
(winner (or var iterate::*result-var*)))
`(progn
(with ,max-val = nil)
(with ,winner = nil)
- (cond
- ((null ,max-val)
- (setq ,winner ,expr)
- (setq ,max-val (funcall ,func ,winner))
- (t
- (let* ((,temp1 ,expr)
- (,temp2 (funcall ,func ,temp1)))
- (when (> ,temp2 ,max-val)
- (setq ,max-val ,temp2)
- (setq ,winner ,temp1))))))
- (finally (leave ,winner)))))
+ (let* ((,temp1 ,expr)
+ (,temp2 (funcall ,func ,temp1)))
+ (when (or (null ,max-val) (> ,temp2 ,max-val))
+ (setq ,winner ,temp1 ,max-val ,temp2))))))
@end lisp
+@c This example differs from the built-in finder:
+@c - The built-in one specifies the clause's value (el so far)
+@c (trivial to implement: add ,winner at end of progn)
+@c - The built-in one accepts an (el max-val) tuple var spec.
+@c - Influence of (the type var) on type declarations
+
Note that if no @code{into} variable is supplied, we use
@code{iterate::*result-var*}, which contains the internal variable
into which all clauses place their results. If this variable is bound
by some clause, then @iter{} will return its value automatically;
otherwise, @code{nil} will be returned.
+@c The original example had four flaws:
+@c - ,expr and ,func occured twice in expansion
+@c - (finally (leave ,winner)) breaks because FINALLY does not walk
+@c its forms, so LEAVE does not work inside FINALLY.
+@c - Do not use (finally (return ,winner)) either, as that would
+@c always return winner, even in case of ... INTO nil.
+@c - Value of clause as form undefined, unlike all built-in clauses
+
@menu
* Writing Drivers::
* Extensibility Aids::
diff -rN -u old-iterate/iterate-test.lisp new-iterate/iterate-test.lisp
--- old-iterate/iterate-test.lisp 2014-07-28 13:33:36.000000000 -0700
+++ new-iterate/iterate-test.lisp 2014-07-28 13:33:36.000000000 -0700
@@ -1,7 +1,7 @@
;;; Test cases for Iterate.
;;; Copyright (c) 2003 Andreas Fuchs <asf@boinkor.net>
-;;; Copyright (c) 2004-2005 Joerg Hoehle <hoehle@users.sourceforge.net>
+;;; Copyright (c) 2004-2007 Joerg Hoehle <hoehle@users.sourceforge.net>
;;; License:
;; Permission is hereby granted, free of charge, to any person
@@ -673,6 +673,11 @@
(if (next x) (collect i)))
(0 3))
+(deftest if.2
+ (iter (generate x in-vector '#(t nil nil t) with-index i)
+ (if (next x) (collect i)))
+ (0 3))
+
(deftest or.1
(iter (generate x in '(a nil nil 1))
(generate y in-vector '#(2 #\c #\d))
@@ -984,6 +989,15 @@
(collect i)))
(1 -1 3 -1 5))
+(deftest first-time-p.0
+ (with-output-to-string (*standard-output*)
+ (iter (for el in '(nil 1 2 nil 3))
+ (when el
+ (unless (first-time-p)
+ (princ ", "))
+ (princ el))))
+ "1, 2, 3")
+
(deftest first-time-p.1
(iter (for i to 5)
(if (first-time-p) (collect -1))
@@ -1479,7 +1493,7 @@
(sum-of-squares el))
14)
-(deftest defmacro-clause
+(deftest defmacro-clause.1
(defmacro-clause (multiply.clause expr &optional INTO var)
"from testsuite"
`(reducing ,expr by #'* into ,var initial-value 1))
@@ -1591,6 +1605,45 @@
(collect (list (next e) e i)))
((a a 0) (b b 1) (c c 2)))
+;; The original example had three bugs:
+;; - ,expr and ,func occured twice in expansion
+;; - (finally (leave ,winner)) breaks because FINALLY does not walk
+;; its forms, so LEAVE does not work inside FINALLY.
+;; - Do not use (finally (RETURN ,winner)) either, as that would
+;; always return accumulated value, even in case of ... INTO nil.
+(deftest defmacro-clause.2
+ (defmacro-clause (FINDING expr MAXING func &optional INTO var)
+ "Iterate paper demo example"
+ (let ((max-val (gensym "MAX-VAL"))
+ (temp1 (gensym "EL"))
+ (temp2 (gensym "VAL"))
+ (winner (or var iterate::*result-var*)))
+ `(progn
+ (with ,max-val = nil)
+ (with ,winner = nil)
+ (let* ((,temp1 ,expr)
+ (,temp2 (funcall ,func ,temp1)))
+ (when (or (null ,max-val) (> ,temp2 ,max-val))
+ (setq ,winner ,temp1 ,max-val ,temp2)))
+ #|(finally (return ,winner))|# )))
+ (FINDING expr MAXING func &optional INTO var))
+
+(deftest maxing.1
+ (iter (for i in-vector #(1 5 3))
+ (finding i :maxing #'identity))
+ 5)
+
+(deftest maxing.2
+ (iter (for i in-vector #(1 5 3))
+ (finding i maxing #'identity into foo))
+ nil)
+
+(deftest maxing.3
+ (iter (for i in-vector #(2 5 4))
+ (finding i maxing #'identity into foo)
+ (when (evenp i) (sum i)))
+ 6)
+
(deftest display.1
(let ((*standard-output* (make-broadcast-stream)))
(display-iterate-clauses) t)