Skip to content

Commit 1eeab59

Browse files
Apply changes from Linus Björnstam.
1 parent 7c4ac04 commit 1eeab59

File tree

10 files changed

+155
-68
lines changed

10 files changed

+155
-68
lines changed

compose.scm

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
;; Fold is as defined in srfi-1.
2+
;; for r6rs it can be substituted for fold-left
3+
14
(define (compose . functions)
25
(define (make-chain thunk chain)
36
(lambda args
47
(call-with-values (lambda () (apply thunk args)) chain)))
58
(if (null? functions)
69
values
7-
(fold-left make-chain (car functions) (cdr functions))))
10+
(fold make-chain (car functions) (cdr functions))))

srfi-171.html

+80-54
Original file line numberDiff line numberDiff line change
@@ -222,35 +222,47 @@ <h3 id="vector-transduce">vector-transduce</h3>
222222
<br />
223223
<code>(vector-transduce</code> <em>xform f identity vec</em><code>)</code></p>
224224

225-
<p>Same as <code>transduce</code>, but reduces over a vector instead of a list.</p>
225+
<p>Same as <code>list-transduce</code>, but reduces over a vector instead of a list.</p>
226226

227227

228228
<h3 id="string-transduce">string-transduce</h3>
229229
<p><code>(string-transduce</code> <em>xform f str</em><code>)</code>
230230
<br />
231231
<code>(string-transduce</code> <em>xform f identity str</em><code>)</code></p>
232232

233-
<p>Same as <code>transduce</code>, but for strings.</p>
233+
<p>Same as <code>list-transduce</code>, but for strings.</p>
234234

235235

236236
<h3 id="bytevector-u8-transduce">bytevector-u8-transduce</h3>
237237
<p><code>(bytevector-u8-transduce</code> <em>xform f bvec</em><code>)</code>
238238
<br />
239239
<code>(bytevector-u8-transduce</code> <em>xform f identity bvec</em><code>)</code></p>
240240

241-
<p>Same as transduce, but for u8-bytevectors.</p>
241+
<p>Same as <code>list-transduce</code>, but for u8-bytevectors.</p>
242242

243243

244244
<h3 id="port-transduce">port-transduce</h3>
245-
<p><code>(port-transduce</code> <em>xform f reader port</em><code>)</code>
246-
<br />
247-
<code>(port-transduce</code> <em>xform f init reader port</em><code>)</code></p>
248-
249-
<p> Applies <code>(xform f)</code> to every value produced by <code>(reader port)</code> until
250-
<code>#eof-object</code> is returned.</p>
245+
<p><code>(port-transduce</code> <em>xform f reader</em><code>)</code>
246+
<br />
247+
<code>(port-transduce</code> <em>xform f reader port</em><code>)</code>
248+
<br />
249+
<code>(port-transduce</code> <em>xform f init reader port</em><code>)</code></p>
250+
251+
<p> If <em>port</em> is provided, it applies <code>(xform f)</code> to every value
252+
produced by <code>(reader port)</code> until <code>#eof-object</code> is returned.
253+
If <em>port</em> is not provided, it calls <em>reader</em> without arguments until
254+
<code>#eof-object</code> is returned.
255+
</p>
251256

252257
<p><code>(port-transduce (tfilter odd?) rcons read (open-input-string "1 2 3 4"))</code>
253-
=&gt; (2 4)</p>
258+
=&gt; (2 4)</p>
259+
260+
<h3 id="generator-transduce">generator-transduce</h3>
261+
<p><code>(generator-transduce</code> <em>xform f gen</em><code>)</code>
262+
<br />
263+
<code>(generator-transduce</code> <em>xform f init gen</em><code>)</code></p>
264+
265+
<p> Same as list-transduce, but for srfi-158-styled generators</p>
254266

255267

256268
<h2 id="reducers">Reducers</h2>
@@ -289,7 +301,7 @@ <h3 id="revery-pred"><code>(revery</code> <em>pred?</em><code>)</code></h3>
289301
<p>The reducer version of every. Stops the transduction and returns
290302
(reduced #f) if any (pred? value) returns #f. If every (pred? value)
291303
returns true, it returns the result of the last invocation of (pred?
292-
value).</p>
304+
value). The identity is <code>#t</code>.</p>
293305

294306
<p><pre>(list-transduce
295307
(tmap (lambda (x) (+ x 1)))
@@ -329,13 +341,17 @@ <h3 id="tfilter-map-proc"><code>(tfilter-map</code> <em>proc</em><code>)</code><
329341
Must be stateless.</p>
330342

331343

332-
<h3 id="treplace-map"><code>(treplace</code> <em>map</em><code>)</code></h3>
333-
<p>Returns a transducer which uses any value as a key in
334-
<em>map</em>. If a mapping is found, the value of that mapping is
335-
returned, otherwise it just returns the original value.</p>
344+
<h3 id="treplace-mapping"><code>(treplace</code> <em>mapping</em><code>)</code></h3>
345+
<p>Returns a transducer which checks for the presence of any value passed through it in
346+
<em>mapping</em>. If a mapping is found, the value of that mapping is
347+
returned, otherwise it just returns the original value.</p>
336348

337-
<p>Must not keep any internal state. Modifying the map after treplace
338-
has been instantiated is an error.</p>
349+
<p><em>mapping</em> is an association list (using equal? to compare keys), a hash-table,
350+
a one-argument procedure taking one argument and either producing that same argument
351+
or a replacement value, or another implementation-defined mapping object.</p>
352+
353+
<p>Must not keep any internal state. Modifying the mapping while it's in use by treplace
354+
is an error.</p>
339355

340356

341357
<h3 id="tdrop-n"><code>(tdrop</code> <em>n</em><code>)</code></h3>
@@ -392,7 +408,7 @@ <h3 id="tflatten"><code>tflatten</code></h3>
392408

393409

394410

395-
<h3 id="tdelete-neighbor-dupes"><code>(tdelete-neighbour-dupes <em>[equality-predicate]</em>)</code></h3>
411+
<h3 id="tdelete-neighbor-dupes"><code>(tdelete-neighbor-dupes <em>[equality-predicate]</em>)</code></h3>
396412
<p>Returns a transducer that removes any directly following duplicate
397413
elements. The default <em>equality-predicate</em> is <code>equal?</code>.</p>
398414

@@ -500,20 +516,25 @@ <h3 id="string-reduce"><code>(string-reduce</code> <em> f identity str</em><code
500516
<p> The string version of <code>list-reduce</code></p>
501517

502518

503-
<h3 id="string-reduce"><code>(port-reduce</code> <em> f identity reader port</em><code>)</code></h3>
519+
<h3 id="port-reduce"><code>(port-reduce</code> <em> f identity reader port</em><code>)</code></h3>
504520
<p> The port version of <code>list-reducer</code>. It reduces over <em>port</em> using
505521
<em>reader</em> until <em>reader</em> returns <code>#eof-object</code>.</p>
506522

507523

524+
<h3 id="generator-reduce"><code>(generator-reduce</code> <em> f identity gen</em><code>)</code></h3>
525+
<p> The port version of <code>list-reducer</code>. It reduces over <em>gen</em> until it returns
526+
527+
<code>#eof-object</code>.</p>
528+
508529

509530
<h1 id="sample-implementation">Sample implementation</h1>
510531

511532
<p> The sample implementation is written in Guile, but should be
512-
straightforward to port since it uses no guile-specific features
513-
apart from guile's hash-table implementation. In fact, I am quite
514-
certain that it is written for clarity instead of speed, but should
515-
be plenty fast anyway. The low-hanging fruit for optimization is to
516-
replace the composed transducers (such as <code>tappend-map</code>
533+
straightforward to port since it uses no guile-specific features
534+
apart from guile's hash-table implementation. In fact, I am quite
535+
certain that it is written for clarity instead of speed, but should
536+
be plenty fast anyway. The low-hanging fruit for optimization is to
537+
replace the composed transducers (such as <code>tappend-map</code>
517538
and <code>tfilter-map</code>) with non-composed implementations.</p>
518539

519540
<p> Another optimization would be to return whether or not a reducer
@@ -523,43 +544,48 @@ <h1 id="sample-implementation">Sample implementation</h1>
523544

524545
<h1 id="acknowledgements">Acknowledgements</h1>
525546

526-
<p>First of all, this would not have been done without Rich Hickey who
527-
introduced transducers into Clojure. His talks were important for me
528-
to grasp the basics of transducers. Then I would like to thank large
529-
parts of the Clojure community for also struggling with
530-
understanding transducers. The amount of material produced
531-
explaining them in general, and Clojure's implementation
532-
specifically, has been instrumental in letting me make this a
547+
<p> First of all, this would not have been done without Rich Hickey who
548+
introduced transducers into Clojure. His talks were important for me
549+
to grasp the basics of transducers. Then I would like to thank large
550+
parts of the Clojure community for also struggling with
551+
understanding transducers. The amount of material produced
552+
explaining them in general, and Clojure's implementation
553+
specifically, has been instrumental in letting me make this a
533554
clean-room implementation.</p>
534555

535-
<p>I'd also like to thank Juanpe Bolivar who implemented pure transducers
536-
for c++ (in the Atria library) and did a wonderful presentation about them.</p>
556+
<p> In the same vein I would like to direct a thank you to Juanpe Bolivar who
557+
implemented pure transducers for c++ (in the Atria library) and did a
558+
wonderful presentation about them.</p>
559+
560+
<p> I would also like to thank John Cowan, Duy Nguyen and Lassi Kortela for
561+
their input during the SRFI process. </p>
537562

538563
<p>Lastly I would like to thank Arthur Gleckler who showed interest in
539564
my implementation of transducers and convinced me to make this SRFI.</p>
540565

566+
541567
<h1 id="copyright">Copyright</h1>
542568

543-
<p>Copyright (C) Linus Björnstam (2019).</p>
544-
545-
<p>Permission is hereby granted, free of charge, to any person
546-
obtaining a copy of this software and associated documentation files
547-
(the “Software”), to deal in the Software without restriction,
548-
including without limitation the rights to use, copy, modify, merge,
549-
publish, distribute, sublicense, and/or sell copies of the Software,
550-
and to permit persons to whom the Software is furnished to do so,
551-
subject to the following conditions:</p>
552-
553-
<p>The above copyright notice and this permission notice shall be
554-
included in all copies or substantial portions of the Software.</p>
555-
556-
<p>THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
557-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
558-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
559-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
560-
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
561-
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
562-
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
563-
SOFTWARE.</p>
569+
<p> Copyright (C) Linus Björnstam (2019).</p>
570+
571+
<p> Permission is hereby granted, free of charge, to any person
572+
obtaining a copy of this software and associated documentation files
573+
(the “Software”), to deal in the Software without restriction,
574+
including without limitation the rights to use, copy, modify, merge,
575+
publish, distribute, sublicense, and/or sell copies of the Software,
576+
and to permit persons to whom the Software is furnished to do so,
577+
subject to the following conditions:</p>
578+
579+
<p> The above copyright notice and this permission notice shall be
580+
included in all copies or substantial portions of the Software.</p>
581+
582+
<p> THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
583+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
584+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
585+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
586+
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
587+
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
588+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
589+
SOFTWARE.</p>
564590

565591
<hr> <address>Editor: <a href="mailto:srfi-editors+at+srfi+dot+schemers+dot+org">Arthur A. Gleckler</a></address></body></html>

srfi/171-impl.scm

+18-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939

4040

4141

42+
4243
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4344
;; Reducing functions meant to be used at the end at the transducing
4445
;; process. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -130,13 +131,25 @@
130131

131132
(define port-transduce
132133
(case-lambda
134+
((xform f by)
135+
(generator-transduce xform f by))
133136
((xform f by port)
134137
(port-transduce xform f (f) by port))
135138
((xform f init by port)
136139
(let* ((xf (xform f))
137140
(result (port-reduce xf init by port)))
138141
(xf result)))))
139142

143+
(define generator-transduce
144+
(case-lambda
145+
((xform f gen)
146+
(generator-transduce xform f (f) gen))
147+
((xform f init gen)
148+
(let* ((xf (xform f))
149+
(result (generator-reduce xf init gen)))
150+
(xf result)))))
151+
152+
140153
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
141154
;; Transducers! ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
142155

@@ -185,7 +198,10 @@
185198
x))))
186199
((hash-table? map)
187200
(lambda (x)
188-
(hash-table-ref map x x)))))
201+
(hash-table-ref/default map x x)))
202+
((procedure? map) map)
203+
(else
204+
(error "Unsupported mapping in treplace" map))))
189205

190206

191207
(define (treplace map)
@@ -236,6 +252,7 @@
236252
result)))))))
237253

238254

255+
239256
(define ttake-while
240257
(case-lambda
241258
((pred) (ttake-while pred (lambda (result input) result)))

srfi/171.sld

+11-8
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
(srfi 171 meta))
2222
(cond-expand
2323
(gauche (import (only (gauche base) compose reverse!)))
24-
(chibi (import (only (srfi 1) reverse!))))
24+
(chibi (import (only (srfi 1) fold reverse!))))
2525
(export rcons reverse-rcons
2626
rcount
2727
rany
@@ -32,6 +32,7 @@
3232
string-transduce
3333
bytevector-u8-transduce
3434
port-transduce
35+
generator-transduce
3536

3637
tmap
3738
tfilter
@@ -53,13 +54,15 @@
5354
tenumerate
5455
tlog)
5556

56-
;; compose.scm uses fold-left, not available in
57-
;; Chibi. This is all we need for this SRFI
5857
(cond-expand
59-
(chibi (begin (define compose
60-
(lambda (f g)
61-
(lambda args
62-
(f (apply g args)))))))
63-
(else (begin)))
58+
(chibi (begin
59+
(define (compose . functions)
60+
(define (make-chain thunk chain)
61+
(lambda args
62+
(call-with-values (lambda () (apply thunk args)) chain)))
63+
(if (null? functions)
64+
values
65+
(fold make-chain (car functions) (cdr functions))))))
66+
(else (begin)))
6467

6568
(include "171-impl.scm"))

srfi/171/meta.sld

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
vector-reduce
2222
string-reduce
2323
bytevector-u8-reduce
24-
port-reduce)
24+
port-reduce
25+
generator-reduce)
2526

2627
(include "../srfi-171-meta.scm"))
2728

srfi/srfi-171-meta.scm

+9
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,12 @@
8383
(if (reduced? acc)
8484
(unreduce acc)
8585
(loop (reader port) acc))))))
86+
87+
(define (generator-reduce f identity gen)
88+
(let loop ((val (gen)) (acc identity))
89+
(if (eof-object? val)
90+
acc
91+
(let ((acc (f acc val)))
92+
(if (reduced? acc)
93+
(unreduce acc)
94+
(loop (gen) acc))))))

srfi/srfi-171.scm

+7-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,13 @@
2323
rcount
2424
rany
2525
revery
26-
list-transduce vector-transduce string-transduce bytevector-u8transduce port-transduce
26+
list-transduce
27+
vector-transduce
28+
string-transduce
29+
bytevector-u8transduce
30+
port-transduce
31+
generator-transduce
32+
2733
tmap
2834
tfilter
2935
tremove

srfi/srfi-171/meta.scm

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
vector-reduce
2626
string-reduce
2727
bytevector-u8-reduce
28-
port-reduce))
28+
port-reduce
29+
generator-reduce))
2930

3031
(include "../srfi-171-meta.scm")
3132

tests-r7rs.scm

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
(import (scheme base)
55
(scheme char)
66
(scheme list)
7-
(scheme read)
7+
(scheme read)
88
(srfi 171))
99
(cond-expand
1010
(gauche (import (only (gauche base) compose)

0 commit comments

Comments
 (0)