diff --git a/documentation/doc.html b/documentation/doc.html index ee926ea..65838c4 100644 --- a/documentation/doc.html +++ b/documentation/doc.html @@ -92,7 +92,7 @@ (loop ((:for a (in-list '(1 2 3 4))) ;; this works because :acc bindings are promoted "outwards". (:break final) - (:acc final (in-value (initial #f) #t (if (= 3 a)))) + (:acc final (in-value (:initial #f) #t (:if (= 3 a)))) (:acc acc (listing (cons a b)))))

This means that any clause above the final binding will be executed an extra time before the loop exits:

@@ -166,26 +166,26 @@
 
Scheme syntax: stop-after
(:for binding (stop-after iterator pred))

Binds binding to the values produced by iterator until pred applied to that value returns true. It then produces that last value. The iterator is then considered exhausted. Useful in subloops where one might want to end internal iteration without :break-ing.

:acc-clauses

Accumulating clauses differ from :for-clauses in 2 significant ways. They have a final value available in the final-expr, and they keep their state throughout the loop. In the case of a loop with one subloop, the :for-clauses reset their state every time the subloop is entered. :acc-clauses will always keep their state.

Another small thing is that for some :acc-clauses, the binding may sometimes only be visible to the user in the final-expr, but like :for-clauses they sometimes offer the programmer to name the loop variables.

-

Many accumulating clauses support an if form. If such a clause is given, accumulation will only happen if the guard clause returns true.

-
Scheme syntax: listing
(:acc binding (listing [(:initial init)] expr [if guard]))

Accumulates expr into a list. ´bindingis only accesible in the final-expression. The list is in the same order as the loop bodies were evaluated. Ifinitialis given that will be used as the tail of the accumulated results. It defaults to’()`.

-
Scheme syntax: listing-reverse
(:acc binding (listing-reverse [(:initial init)] expr [if guard]))

The same as listing but the resulting list in in reverse order. If the order of the resulting list does not matter, this will be faster than the regular listing as it will not preform any reverse at the end.

-
Scheme syntax: appending
(:acc binding (appending [(:initial init)] expr [if guard]))

expr evaluates to a list that is then appended to the accumulated result.

+

Many accumulating clauses support an :if form. If such a clause is given, accumulation will only happen if the guard clause returns true.

+
Scheme syntax: listing
(:acc binding (listing [(:initial init)] expr [(:if guard)]))

Accumulates expr into a list. ´bindingis only accesible in the final-expression. The list is in the same order as the loop bodies were evaluated. Ifinitialis given that will be used as the tail of the accumulated results. It defaults to’()`.

+
Scheme syntax: listing-reverse
(:acc binding (listing-reverse [(:initial init)] expr [(:if guard)]))

The same as listing but the resulting list in in reverse order. If the order of the resulting list does not matter, this will be faster than the regular listing as it will not preform any reverse at the end.

+
Scheme syntax: appending
(:acc binding (appending [(:initial init)] expr [(:if guard)]))

expr evaluates to a list that is then appended to the accumulated result.

 (loop ((:for elt (in-list '((1 2) (3 4))))
        (:acc acc (appending (:initial '(0)) elt)))
   => acc)
   ;; => (0 1 2 3 4)     
-        
Scheme syntax: appending-reverse
(:acc binding (appending-reverse [(:initial init)] expr [if guard]))

expr evaluates to a list that is then consed element by element onto the already accumulated results. The default initial value is '().

+
Scheme syntax: appending-reverse
(:acc binding (appending-reverse [(:initial init)] expr [(:if guard)]))

expr evaluates to a list that is then consed element by element onto the already accumulated results. The default initial value is '().

 (loop ((:for elt (in-list '((1 2) (3 4))))
        (:acc acc (appending-reverse (:initial '(0)) elt)))
   => acc)
   ;; => (4 3 2 1 0)
-        
Scheme syntax: summing
(:acc binding (summing [(:initial init)] expr [(if guard)]))

Adds the result of expr together using +. The default initial value is 0.

-
Scheme syntax: multiplying
(:acc binding (multiplying [(:initial init)] expr [(if guard)]))

Multiplies the result of expr using *. The default initial value is 1.

-
Scheme syntax: hashing
(:acc binding (hashing [(:initial init)] key value [(if guard)]))

Adds the mapping (key => value) to the hashtable binding using equal?-hashing. The initial hash table is an empty hash-table. binding is bound to the hash table throughout the loop, and its content can be mutated in the loop body.

-
Scheme syntax: hashving
(:acc binding (hashving [(:initial init)] key value [(if guard)]))

Adds the mapping (key => value) to the hashtable binding using eqv?-hashing. The initial hash table is an empty hash-table. binding is bound to the hash table throughout the loop, and its content can be mutated in the loop body.

-
Scheme syntax: hashqing
(:acc binding (hashqing [(:initial init)] key value [(if guard)]))

Adds the mapping (key => value) to a hashtable using eq?-hashing. The initial hash table is an empty hash-table.binding is bound to the hash table throughout the loop, and its can be mutated in the loop body.

+
Scheme syntax: summing
(:acc binding (summing [(:initial init)] expr [(:if guard)]))

Adds the result of expr together using +. The default initial value is 0.

+
Scheme syntax: multiplying
(:acc binding (multiplying [(:initial init)] expr [(:if guard)]))

Multiplies the result of expr using *. The default initial value is 1.

+
Scheme syntax: hashing
(:acc binding (hashing [(:initial init)] key value [(:if guard)]))

Adds the mapping (key => value) to the hashtable binding using equal?-hashing. The initial hash table is an empty hash-table. binding is bound to the hash table throughout the loop, and its content can be mutated in the loop body.

+
Scheme syntax: hashving
(:acc binding (hashving [(:initial init)] key value [(:if guard)]))

Adds the mapping (key => value) to the hashtable binding using eqv?-hashing. The initial hash table is an empty hash-table. binding is bound to the hash table throughout the loop, and its content can be mutated in the loop body.

+
Scheme syntax: hashqing
(:acc binding (hashqing [(:initial init)] key value [(:if guard)]))

Adds the mapping (key => value) to a hashtable using eq?-hashing. The initial hash table is an empty hash-table.binding is bound to the hash table throughout the loop, and its can be mutated in the loop body.

Scheme syntax: vectoring
(:acc binding [index] (vectoring expr [(:length len) [(:fill fill)]]))

Accumulates the result of expr into a vector. If len and fill is given the vector will be at most len elements long and any unfilled indexes will contain the element fill. The loop will exit when len elements have been accumulated.

If length is not given, the vector will be expanded as required.

A vectoring clause adds an implicit (:break (= index len)) after the vectoring clause. Once the last element of the vector is filled, the loop will stop and no subsequent clauses or body will be executed.

diff --git a/documentation/doc.xml b/documentation/doc.xml index 5545149..b0fabbf 100644 --- a/documentation/doc.xml +++ b/documentation/doc.xml @@ -140,7 +140,7 @@ (loop ((:for a (in-list '(1 2 3 4))) ;; this works because :acc bindings are promoted "outwards". (:break final) - (:acc final (in-value (initial #f) #t (if (= 3 a)))) + (:acc final (in-value (:initial #f) #t (:if (= 3 a)))) (:acc acc (listing (cons a b))))) @@ -388,23 +388,23 @@ Another small thing is that for some :acc-clauses, the `binding` may sometimes only be visible to the user in the `final-expr`, but like :for-clauses they sometimes offer the programmer to name the loop variables. - Many accumulating clauses support an `if` form. If such a clause is given, accumulation will only happen if the guard clause returns true. + Many accumulating clauses support an `:if` form. If such a clause is given, accumulation will only happen if the guard clause returns true. -
(:acc binding (listing [(:initial init)] expr [if guard]))
+
(:acc binding (listing [(:initial init)] expr [(:if guard)]))
Accumulates `expr` into a list. ´binding` is only accesible in the final-expression. The list is in the same order as the loop bodies were evaluated. If `initial` is given that will be used as the tail of the accumulated results. It defaults to `'()`.
-
(:acc binding (listing-reverse [(:initial init)] expr [if guard]))
+
(:acc binding (listing-reverse [(:initial init)] expr [(:if guard)]))
The same as `listing` but the resulting list in in reverse order. If the order of the resulting list does not matter, this will be faster than the regular listing as it will not preform any reverse at the end.
-
(:acc binding (appending [(:initial init)] expr [if guard]))
+
(:acc binding (appending [(:initial init)] expr [(:if guard)]))
`expr` evaluates to a list that is then appended to the accumulated result. @@ -417,7 +417,7 @@
-
(:acc binding (appending-reverse [(:initial init)] expr [if guard]))
+
(:acc binding (appending-reverse [(:initial init)] expr [(:if guard)]))
`expr` evaluates to a list that is then consed element by element onto the already accumulated results. The default initial value is `'()`. @@ -430,31 +430,31 @@
-
(:acc binding (summing [(:initial init)] expr [(if guard)]))
+
(:acc binding (summing [(:initial init)] expr [(:if guard)]))
Adds the result of `expr` together using `+`. The default initial value is 0.
-
(:acc binding (multiplying [(:initial init)] expr [(if guard)]))
+
(:acc binding (multiplying [(:initial init)] expr [(:if guard)]))
Multiplies the result of `expr` using `*`. The default initial value is 1.
-
(:acc binding (hashing [(:initial init)] key value [(if guard)]))
+
(:acc binding (hashing [(:initial init)] key value [(:if guard)]))
Adds the mapping `(key => value)` to the hashtable `binding` using equal?-hashing. The initial hash table is an empty hash-table. `binding` is bound to the hash table throughout the loop, and its content can be mutated in the loop body.
-
(:acc binding (hashving [(:initial init)] key value [(if guard)]))
+
(:acc binding (hashving [(:initial init)] key value [(:if guard)]))
Adds the mapping `(key => value)` to the hashtable `binding` using eqv?-hashing. The initial hash table is an empty hash-table. `binding` is bound to the hash table throughout the loop, and its content can be mutated in the loop body.
-
(:acc binding (hashqing [(:initial init)] key value [(if guard)]))
+
(:acc binding (hashqing [(:initial init)] key value [(:if guard)]))
Adds the mapping `(key => value)` to a hashtable using eq?-hashing. The initial hash table is an empty hash-table.`binding` is bound to the hash table throughout the loop, and its can be mutated in the loop body.
diff --git a/goof-impl.scm b/goof-impl.scm index fab2f1e..70d9be8 100644 --- a/goof-impl.scm +++ b/goof-impl.scm @@ -33,7 +33,7 @@ ;; Auxiliary syntax for the iterators. :gen ;; auxiliary syntax for some accumulators - :initial + :initial :if ;; auxiliary auxiliary syntax ;; for vectoring :length :fill diff --git a/goof/iterators.scm b/goof/iterators.scm index d8030c5..08a353d 100644 --- a/goof/iterators.scm +++ b/goof/iterators.scm @@ -373,12 +373,12 @@ (define-syntax accumulating - (syntax-rules (:initial if :acc) + (syntax-rules (:initial :if :acc) ((accumulating :acc (kons final init) ((var) . x) next . rest) (accumulating :acc (kons final init) ((var cursor) . x) next . rest)) ((accumulating :acc (kons final init) ((var cursor) ((:initial i) . x)) n . rest) (accumulating :acc (kons final i) ((var cursor) x) n . rest)) - ((accumulating :acc (kons final init) ((var cursor) (expr (if check))) n . rest) + ((accumulating :acc (kons final init) ((var cursor) (expr (:if check))) n . rest) (n ((tmp-kons kons)) ((cursor init (if check (tmp-kons expr cursor) cursor))) () @@ -443,18 +443,18 @@ (syntax-rules () ((_ name default-make setter) (define-syntax name - (syntax-rules (:acc if :initial) + (syntax-rules (:acc :if :initial) ((_ :acc ((var) (key value)) n . rest) - (name :acc ((var) (key value (if #t) (:initial default-make))) n . rest)) + (name :acc ((var) (key value (:if #t) (:initial default-make))) n . rest)) ;; either init or if - ((_ :acc ((var) (key value (if guard))) n . rest) - (name :acc ((var) (key value (if guard) (:initial default-make))) n . rest)) + ((_ :acc ((var) (key value (:if guard))) n . rest) + (name :acc ((var) (key value (:if guard) (:initial default-make))) n . rest)) ((_ :acc ((var) (key value (initial init))) n . rest) - (name :acc ((var) (key value (if #t) (:initial init))) n . rest)) + (name :acc ((var) (key value (:if #t) (:initial init))) n . rest)) ;; both init and if - ((_ :acc ((var) (key value (:initial init) (if guard))) n . rest) - (name ((var) (key value (if guard) (:initial init))) n . rest)) - ((_ :acc ((var) (key value (if guard) (:initial init))) n . rest) + ((_ :acc ((var) (key value (:initial init) (:if guard))) n . rest) + (name ((var) (key value (:if guard) (:initial init))) n . rest)) + ((_ :acc ((var) (key value (:if guard) (:initial init))) n . rest) (n ((var init)) ((dummy (if #f #f) (if guard (setter var key value) (if #f #f))))