source: project/wiki/eggref/5/srfi-196 @ 39194

Last change on this file since 39194 was 39194, checked in by gnosis, 3 months ago

Initial revision of the documentation for SRFI-196

File size: 27.5 KB
Line 
1== [[https://srfi.schemers.org/srfi-196/|SRFI-196: Range Objects]]
2=== Abstract
3Ranges are collections somewhat similar to vectors, except that they are immutable and have algorithmic representations instead of the uniform per-element data structure of vectors. The storage required is usually less than the size of the same collection stored in a vector and the time needed to reference a particular element is typically less for a range than for the same collection stored in a list. This SRFI defines a large subset of the sequence operations defined on lists, vectors, strings, and other collections. If necessary, a range can be converted to a list, vector, or string of its elements or a generator that will lazily produce each element in the range.
4
5For more information, see: [[https://srfi.schemers.org/srfi-196/|SRFI-196: Range Objects]]
6=== Rationale
7One of the most common things to do in programming is to execute a block of code a fixed number of times, with access to the index used for the iteration. Indeed, it is so common that there is generally a standard syntax for providing it, generally involving the keyword for (or if not, as in Fortran and Lisp, the word do). It is also usual to be able to provide a lower bound, (generally defaulting to 0 or 1) as well as a step (generally defaulting to 1) which allows iterations through a sequence of odd numbers, or multiples of 10, or whatever.
8
9Languages with higher order functions, however, provide a second approach to such loops: construct a sequence of numbers and apply a function to each element of the sequence. SRFI 1's iota and the standard for-each procedures make this easy: {{(for-each (lambda (i) ...) (iota 0 10))}} will execute the expressions represented as ... with {{i}} bound to the numbers 0 through 9, as the generated list includes the lower bound and excludes the upper bound.
10
11This approach is less feasible as the number of numbers grows. To iterate a million times involves constructing a list of a million numbers to be iterated over and immediately discarded as garbage. This is not something you want to do in the inner loop of your code. The range objects of this SRFI represent such sequences using (as a rule) a small fixed amount of storage. Using {{(range-for-each (lambda (i) ...) (numeric-range 0 1000000))}} iterates a million times but with less space overhead than iota's list of ten elements. They can be thought of as compactly stored vectors.
12
13In addition, there are other sequences besides integers from which a range can be drawn. In particular, inexact numbers can also specify ranges: {{(numeric-range 0.0 1.0 0.1)}} specifies the sequence 0.0, 0.1, ... 0.9, at least when inexact numbers are represented as IEEE 754 binary double floats (as is usually the case). Roundoff error is still possible when multiplying, but it is greatly reduced compared to accumulated error by repeated adding.
14
15The rationale for string-range is to provide efficient random access to strings. There have been many attempts to ensure O(1) reference to string characters, such as string cursors, UTF-32 encoding, SRFI 135 texts, immutable strings, and so on. Because the range-ref procedure for a string created through string-range runs in O(1) time in the length of the string, a range created by string-range can efficiently access arbitrary characters of the range.
16=== Specification
17==== Preliminary notes
18===== Ranges belong to a disjoint type.
19===== Ranges provide certain running time guarantees.
20===== With each range, we associate two lengths of time, the average accessing time and the total accessing time.
21The total accessing time is the average accessing time multiplied by the length of the range. In the runtime guarantees below, the time spent in arguments designated by {{pred}}, equal, or {{proc}} is ignored.
22===== Unless otherwise noted, procedures in this SRFI that return ranges allocate at most O(1) new locations (see R[57]RS section 3.4 for further information). Such ranges are known as compact ranges. Procedures marked as returning expanded ranges allocate at most O(n) locations, where {{n}} is the number of elements in the range.
23===== This SRFI recommends, but does not require, that Scheme implementations which also provide SRFI 42 modify it so that the typed generator :range also accepts a single argument which is a range in the sense of this SRFI. This feature should be used with caution, as SRFI 42 loops expect that :range iterates only over exact rationals.
24===== The following names are used for arguments to procedures:
25
26<parameter>obj</parameter>
27
28Any Scheme object.
29
30<parameter>range</parameter>
31
32A range object.
33
34<parameter>pred</parameter>
35
36A predicate that accepts zero or more arguments.
37
38<parameter>equal</parameter>
39
40A predicate that accepts two arguments and returns a boolean value. It is not necessarily an equivalence relation.
41
42<parameter>length</parameter>
43
44An exact positive integer.
45
46<parameter>proc</parameter>
47
48A procedure that accepts zero or more arguments and returns zero or more values.
49
50<parameter>list</parameter>
51
52A Scheme list.
53
54<parameter>vector</parameter>
55
56A Scheme vector.
57
58<parameter>string</parameter>
59
60A Scheme string.
61===== It is an error (unless otherwise noted) if the procedures are passed arguments that do not have the type implied by the argument names.
62==== Constructors
63
64<procedure>(range length indexer)</procedure>
65
66Returns a range whose length (number of elements) is length. The indexer procedure returns the nth element (where {{0 ≀ n < length}}) of the range, given {{n}}. This procedure must run in O(1) time. The range returned is compact, although indexer may close over arbitrarily large data structures. The average accessing time of the resulting range is the average time needed to run indexer.
67====== Examples:
68<enscript highlight="scheme">
69(range->list (range 26 (lambda (n) (integer->char (+ 65 n)))))
70  ⇑ (#\A #\B #\C #\D #\E 
 #\Z)
71
72(range->list (range 10 (lambda (n) (expt 1/2 n))))
73  ⇑ (1 1/2 1/4 
 1/512)
74</enscript>
75
76<procedure>(numeric-range start end [step])</procedure>
77
78Returns a numeric range, a special case of a range specified by an inclusive lower bound {{start}}, an exclusive upper bound {{end}}, and a {{step}} value (default 1), all of which can be exact or inexact real numbers.
79
80This constructor produces the sequence
81
82 start, (+ start step), (+ start (* 2 step)), 
, (+ start (* n step)),
83
84where {{n}} is the greatest integer such that {{(+ start (* n step)) < end}} if {{step}} is positive, or such that {{(+ start (* n step)) > end}} if {{step}} is negative. It is is an error if an {{n}} satisfying this condition cannot be determined, or if {{step}} is numerically zero. This procedure must run in O(1) time. The average accessing time of the resulting range must be O(1).
85
86Note that an effect of this definition is that the elements of a range over inexact numbers are enumerated by multiplying the index by the {{step}} value rather than by adding the {{step}} value to itself repeatedly. This reduces the likelihood of roundoff errors.
87====== Examples
88<enscript highlight="scheme">
89(range->list (numeric-range 0 1 1/10))
90  ⇑ (0 1/10 1/5 3/10 2/5 1/2 3/5 7/10 4/5 9/10)
91
92(range->list (numeric-range 5 -5 -3)) ⇑ (5 2 -1 -4)
93</enscript>
94
95<procedure>(iota-range length [start [step]])</procedure>
96
97Returns an iota-numeric range, a special case of a range specified by a length (a non-negative exact integer) as well as an inclusive lower bound {{start}} (default 0) and a {{step}} value (default 1), both of which can be exact or inexact real numbers. This constructor produces the sequence
98
99 start, (+ start step), (+ start (* 2 step)), 
, (+ start (* (- length 1) step)),
100
101This procedure must run in O(1) time. The average accessing time of the resulting range must be O(1).
102
103Note that an effect of this definition is that the elements of a range over inexact numbers are enumerated by multiplying the index by the {{step}} value rather than by adding the {{step}} value to itself repeatedly. This reduces the likelihood of roundoff errors.
104
105<procedure>(vector-range vector)</procedure>
106
107Returns a range whose elements are those of vector. The procedure must run in O(1) time. The average accessing time of the resulting range must be O(1). It is an error to mutate vector.
108====== Example
109<enscript highlight="scheme">
110(range->list (vector-range #(1 3 5 7 9)))
111  ⇑ (1 3 5 7 9)
112</enscript>
113
114<procedure>(string-range string)</procedure>
115
116Returns a range whose elements are those of string. It is an error to mutate string. This procedure must run in O(n) time, where {{n}} is the length of string. The average accessing time of the resulting range must be O(1).
117
118In a Scheme that guarantees O(1) random access to strings, range-ref on a range created by string-range can simply call string-ref, and the resulting range is compact. But if only O(n) access is available, this procedure may have to copy the string's characters into a vector, resulting in an expanded range.
119====== Example
120<enscript highlight="scheme">
121(range->list (string-range "abcde"))
122  ⇑ (#\a #\b #\c #\d #\e)
123</enscript>
124
125<procedure>(range-append range ...)</procedure>
126
127Returns a range whose elements are the elements of the ranges in order. This procedure must run in O(n) + O(k) time, where {{n}} is the total number of elements in all the ranges and {{k}} is the number of ranges. The result is usually expanded but may be compact. The average accessing time of the resulting range is asymptotically bounded by maximum of the average accessing times of the ranges.
128====== Example
129<enscript highlight="scheme">
130(range->list (range-append (numeric-range 0 3)
131                           (numeric-range 3 6)))
132  ⇑ (0 1 2 3 4 5)
133</enscript>
134==== Predicates
135
136<procedure>(range? obj)</procedure>
137
138Returns {{#t}} if obj is a range and {{#f}} otherwise. This procedure must run in O(1) time.
139
140<procedure>(range=? equal range1 range2 ...)</procedure>
141
142Returns {{#t}} if all the ranges are of the same length and if their corresponding values are the same in the sense of equal, and {{#f}} otherwise. The runtime of this procedure is O(s) + O(k), where {{s}} is the sum of the total accessing times of the ranges and {{k}} is the number of ranges.
143====== Examples
144<enscript highlight="scheme">
145(range=? = (numeric-range 10 30) (numeric-range 10 30)) ⇑ #t
146(range=? = (numeric-range 5 10) (numeric-range 6 11)) ⇑ #f
147(range=? eqv? (numeric-range 0 0) (range 0 (lambda (i) i))) ⇑ #t
148</enscript>
149==== Accessors
150
151<procedure>(range-length range)</procedure>
152
153Returns the length (number of elements) of range. This procedure must run in O(1) time.
154====== Example
155<enscript highlight="scheme">
156(range-length (numeric-range 10 30)) ⇑ 20
157</enscript>
158
159<procedure>(range-ref range n)</procedure>
160
161Returns the nth element of range. It is an error if {{n}} is less than 0 or greater than or equal to the length of range. The running time of this procedure must be asymptotically equal to the average accessing time of range.
162====== Examples
163<enscript highlight="scheme">
164(range-ref (numeric-range 10 30) 5) ⇑ 15
165(range-ref (range 2 (lambda (i) (not (zero? i)))) 1) ⇑ #t
166</enscript>
167
168<procedure>(range-first range)</procedure>
169
170Equivalent (in running time as well) to {{(range-ref range 0)}}.
171====== Example
172<enscript highlight="scheme">
173(range-first (numeric-range 10 30)) ⇑ 10
174</enscript>
175
176<procedure>(range-last range)</procedure>
177
178Equivalent (in running time as well) to {{(range-ref range (- (range-length range) 1))}}.
179====== Example
180<enscript highlight="scheme">
181(range-last (numeric-range 10 30)) ⇑ 29
182</enscript>
183==== Iteration
184
185<procedure>(range-split-at range index)</procedure>
186
187Returns two values: {{(range-take range index)}} and {{(range-drop range index)}}. It is an error if index is not an exact integer between 0 and the length of range, both inclusive. This procedure must run in O(1) time.
188====== Example
189<enscript highlight="scheme">
190(let-values (((ra rb) (range-split-at (numeric-range 10 20) 5)))
191  (values (range->list ra) (range->list rb)))
192    ⇑ (10 11 12 13 14)
193      (15 16 17 18 19)
194</enscript>
195
196<procedure>(subrange range start end)</procedure>
197
198Returns a range which contains the elements of range from index {{start}}, inclusive, through index {{end}}, exclusive. This procedure must run in O(1) time. The average accessing time of the resulting range is asymptotically bounded by the average accessing time of range.
199====== Examples
200<enscript highlight="scheme">
201(range->list (subrange (numeric-range 5 15) 5 8))
202  ⇑ (10 11 12)
203
204(range->list (subrange (string-range "abcdefghij") 2 8))
205  ⇑ (#\c #\d #\e #\f #\g #\h)
206</enscript>
207
208<procedure>(range-segment range length)</procedure>
209
210Returns a list of ranges representing the consecutive subranges of length length. The last range is allowed to be shorter than length. The procedure must run in O(k) time, where {{k}} is the number of ranges returned. The average accessing time of the ranges is asymptotically bounded by the average accessing time of range.
211
212<enscript highlight="scheme">
213(map range->list (range-segment (numeric-range 0 12) 4))
214  ⇑ ((0 1 2 3) (4 5 6 7) (8 9 10 11))
215
216(map range->list (range-segment (numeric-range 0 2 1/3) 4))
217  ⇑ ((0 1/3 2/3 1) (4/3 5/3))
218</enscript>
219===== range-take and range-take-right
220====== Syntax
221
222<procedure>(range-take range count)
223
224<procedure>(range-take-right range count)
225====== Description
226Returns a range which contains the first/last count elements of range. The average accessing time of the resulting ranges is asymptotically bounded by the average accessing time of range.
227====== Examples
228<enscript highlight="scheme">
229(range->list (range-take (numeric-range 0 10) 5))
230  ⇑ (0 1 2 3 4)
231
232(range->list (range-take-right (numeric-range 0 10) 5))
233  ⇑ (5 6 7 8 9)
234</enscript>
235===== range-drop and range-drop-right
236====== Syntax
237<procedure>(range-drop range count)</procedure>
238
239<procedure>(range-drop-right range count)</procedure>
240
241====== Description
242Returns a range which contains all except the first/last count elements of range. These procedures must run in O(1) time. The average accessing time of the resulting ranges is asymptotically bounded by the average accessing time respectively of range.
243
244<enscript highlight="scheme">
245(range->list (range-drop (numeric-range 0 10) 5))
246  ⇑ (5 6 7 8 9)
247
248(range->list (range-drop-right (numeric-range 0 10) 5))
249  ⇑ (0 1 2 3 4)
250</enscript>
251
252<procedure>(range-count pred range1 range2 ...)</procedure>
253
254Applies {{pred}} element-wise to the elements of ranges and returns the number of applications which returned true values. If more than one range is given and not all ranges have the same length, range-count terminates when the shortest range is exhausted. The runtime of this procedure is O(s) where {{s}} is the sum of the total accessing times of the ranges.
255====== Examples
256<enscript highlight="scheme">
257(range-count even? (numeric-range 0 10)) ⇑ 5
258(range-count < (numeric-range 0 10 2) (numeric-range 5 15)) ⇑ 5
259</enscript>
260
261<procedure>(range-any pred range1 range2 ...)</procedure>
262
263Applies {{pred}} element-wise to the elements of the ranges and returns true if {{pred}} returns true on any application. Specifically it returns the last value returned by {{pred}}. Otherwise, {{#f}} is returned. If more than one range is given and not all ranges have the same length, range-any terminates when the shortest range is exhausted. The runtime of this procedure is O(s) where {{s}} is the sum of the total accessing times of the ranges.
264====== Examples
265<enscript highlight="scheme">
266(range-any odd? (numeric-range 0 10)) ⇑ #t
267(range-any odd? (numeric-range 0 10 2)) ⇑ #f
268(range-any < (numeric-range 0 10 2) (numeric-range 5 15)) ⇑ #t
269</enscript>
270
271<procedure>(range-every pred range)</procedure>
272
273Applies {{pred}} element-wise to the elements of the ranges and returns true if {{pred}} returns true on every application. Specifically it returns the last value returned by {{pred}} , or {{#t}} if {{pred}} was never invoked. Otherwise, {{#f}} is returned. If more than one range is given and not all ranges have the same length, range-every terminates when the shortest range is exhausted. The runtime of this procedure is O(s) + O(k), where {{s}} is the sum of the total accessing times of the ranges and {{k}} is the number of ranges.
274====== Examples
275<enscript highlight="scheme">
276(range-every integer? (numeric-range 0 10)) ⇑ #t
277(range-every odd? (numeric-range 0 10)) ⇑ #f
278(range-every < (numeric-range 0 10 2) (numeric-range 5 15)) ⇑ #f
279</enscript>
280===== range-map, range-map->list, and range-map->vector
281====== Syntax
282<procedure>(range-map proc range1 range2 ...)</procedure>
283
284<procedure>(range-map->list proc range1 range2 ...)</procedure>
285
286<procedure>(range-map->vector proc range1 range2 ...)</procedure>
287
288====== Description
289Applies {{proc}} element-wise to the elements of the ranges and returns a range/list/vector of the results, in order. If more than one range is given and not all ranges have the same length, these procedures terminate when the shortest range is exhausted. The dynamic order in which {{proc}} is actually applied to the elements is unspecified. The runtime of these procedures is O(s) where {{s}} is the sum of the total accessing times of the ranges. The range-map procedure eagerly computes its result and returns an expanded range. Its average accessing time is O(1).
290====== Examples
291<enscript highlight="scheme">
292(range->list (range-map square (numeric-range 5 10))) ⇑ (25 36 49 64 81)
293
294(range->list (range-map + (numeric-range 0 5) (numeric-range 5 10)))
295  ⇑ (5 7 9 11 13)
296
297(range-map->list square (numeric-range 5 10)) ⇑ (25 36 49 64 81)
298
299(range-map->vector square (numeric-range 5 10)) ⇑ #(25 36 49 64 81)
300</enscript>
301
302<procedure>(range-for-each proc range1 range2 ...)</procedure>
303
304Applies {{proc}} element-wise to the elements of the ranges in order. Returns an unspecified result. If more than one range is given and not all ranges have the same length, range-for-each terminates when the shortest range is exhausted. The runtime of this procedure is O(s) where {{s}} is the sum of the total accessing times of the ranges.
305====== Example
306<enscript highlight="scheme">
307(let ((vec (make-vector 5)))
308  (range-for-each (lambda (i) (vector-set! vec i (* i i)))
309                  (numeric-range 0 5))
310  vec) ⇑ #(0 1 4 9 16)
311</enscript>
312===== range-filter-map and range-filter-map->list
313====== Syntax
314<procedure>(range-filter-map proc range1 range2 ...)</procedure>
315
316<procedure>(range-filter-map->list proc range1 range2 ...)</procedure>
317
318====== Description
319Applies {{proc}} element-wise to the elements of the ranges and returns a range/list of the true values returned by {{proc}}. If more than one range is given and not all ranges have the same length, these procedures terminate when the shortest range is exhausted. The dynamic order in which {{proc}} is actually applied to the elements is unspecified. The range-filter-map procedure eagerly computes its result and returns an expanded range. The runtime of these procedures is O(n) where {{n}} is the sum of the total accessing times of the ranges.
320====== Examples
321<enscript highlight="scheme">
322(range->list (range-filter-map (lambda (x) (and (even? x) (* x x)))
323                               (numeric-range 0 10)))
324  ⇑ (0 4 16 36 64)
325
326(range-filter-map->list (lambda (x y)
327                          (and (< x y) (* x y)))
328                        (numeric-range 0 10 2)
329                        (numeric-range 5 15))
330  ⇑ (0 12 28 48 72)
331</enscript>
332===== range-filter, range-filter->list, range-remove, and range->remove->list
333====== Syntax
334<procedure>(range-filter pred range)</procedure>
335
336<procedure>(range-filter->list pred range)</procedure>
337
338<procedure>(range-remove pred range)</procedure>
339
340<procedure>(range-remove->list pred range)</procedure>
341
342====== Description
343Returns a range/list containing the elements of range that satisfy / do not satisfy {{pred}}. The runtime of these procedures is O(s) where {{s}} is the sum of the total accessing times of the ranges.
344
345The range-filter and range-remove procedures eagerly compute their results and return expanded ranges. Their average accessing time is O(1).
346====== Examples
347<enscript highlight="scheme">
348(range->list (range-filter even? (numeric-range 0 10)))
349  ⇑ (0 2 4 6 8)
350
351(range-filter->list odd? (numeric-range 0 10))
352  ⇑ (1 3 5 7 9)
353
354(range->list (range-remove even? (numeric-range 0 10)))
355  ⇑ (1 3 5 7 9)
356
357(range-remove->list odd? (numeric-range 0 10))
358  ⇑ (0 2 4 6 8)
359</enscript>
360===== range-fold and range-fold-right
361====== Syntax
362<procedure>(range-fold kons nil range1 range2 ...)</procedure>
363
364<procedure>(range-fold-right kons nil range1 range2 ...)</procedure>
365
366====== Description
367Folds {{kons}} over the elements of ranges in order / reverse order. {{kons}} is applied as ({{kons}} state (range-ref range1 i) (range-ref range2 i) 
) where state is the result of the previous invocation and {{i}} is the current index. For the first invocation, nil is used as the first argument. Returns the result of the last invocation, or nil if there was no invocation. If more than one range is given and not all ranges have the same length, these procedures terminate when the shortest range is exhausted. The runtime of these procedures must be O(s) where {{s}} is the sum of the total accessing times of the ranges.
368====== Examples
369<enscript highlight="scheme">
370(range-fold (lambda (n _) (+ 1 n)) 0 (numeric-range 0 30))
371  ⇑ 30
372
373(range-fold + 0 (numeric-range 0 100) (numeric-range 50 70))
374  ⇑ 1380
375
376(range-fold-right xcons '() (numeric-range 0 10))
377  ⇑ (0 1 2 3 4 5 6 7 8 9)
378
379(range-fold-right (lambda (lis x y) (cons (+ x y) lis))
380                  '()
381                  (numeric-range 3 6)
382                  (numeric-range 5 12))
383  ⇑ (8 10 12)
384</enscript>
385==== Searching
386===== range-index and range-index-right
387====== Syntax
388<procedure>(range-index pred range1 range2... )</procedure>
389
390<procedure>(range-index-right pred range1 range2... )</procedure>
391
392====== Description
393Applies {{pred}} element-wise to the elements of ranges and returns the index of the first/last element at which {{pred}} returns true. Otherwise, returns {{#f}}. If more than one range is given and not all ranges have the same length, range-index terminates when the shortest range is exhausted. It is an error if the ranges passed to range-index-right do not all have the same lengths. The runtime of these procedures must be O(s) where {{s}} is the sum of the total accessing times of the ranges.
394====== Examples
395<enscript highlight="scheme">
396(range-index (lambda (x) (> x 10)) (numeric-range 5 15)) ⇑ 6
397
398(range-index odd? (numeric-range 0 10 2)) ⇑ #f
399
400(range-index = (numeric-range 0 12 2) (numeric-range 5 15)) ⇑ 5
401
402(range-index-right odd? (numeric-range 0 5)) ⇑ 3
403</enscript>
404===== range-take-while and range-take-while-right
405====== Syntax
406<procedure>(range-take-while pred range)</procedure>
407
408<procedure>(range-take-while-right pred range)</procedure>
409
410====== Description
411Returns a range containing the leading/trailing elements of range that satisfy {{pred}} up to the first/last one that does not. The runtime of these procedures is asymptotically bounded by the total accessing time of the range. The average accessing time of the resulting range is O(1).
412====== Examples
413<enscript highlight="scheme">
414(range->list (range-take-while (lambda (x) (< x 10))
415                               (numeric-range 5 15)))
416  ⇑ (5 6 7 8 9)
417
418(range->list (range-take-while-right (lambda (x) (> x 10))
419                                     (numeric-range 5 15)))
420  ⇑ (11 12 13 14)
421</enscript>
422===== range-drop-while and range-drop-while-right
423====== Syntax
424<procedure>(range-drop-while pred range)</procedure>
425
426<procedure>(range-drop-while-right pred range)</procedure>
427
428====== Description
429Returns a range that omits leading/trailing elements of range that satisfy {{pred}} until the first/last one that does not. The runtime of these procedures is asymptotically bounded by the total accessing time of the range. The average accessing time of the resulting range is O(1).
430====== Examples
431<enscript highlight="scheme">
432(range->list (range-drop-while (lambda (x) (< x 10))
433                               (numeric-range 5 15)))
434  ⇑ (10 11 12 13 14)
435
436(range->list (range-drop-while-right (lambda (x) (> x 10))
437                                     (numeric-range 5 15)))
438  ⇑ (5 6 7 8 9 10)
439</enscript>
440==== Conversion
441===== range->list, range->vector, range->string
442====== Syntax
443<procedure>(range->list range)</procedure>
444
445<procedure>(range->vector range)</procedure>
446
447<procedure>(range->string range)</procedure>
448
449====== Description
450Returns a list/vector/string containing the elements of range in order. It is an error to modify the result of range->vector or of range->string. In the case of range-> string, it is an error if any element of range is not a character. The running times of these procedures is O(s) where {{s}} is the total accessing time for range.
451====== Examples
452<enscript highlight="scheme">
453(range->list (numeric-range 0 0)) ⇑ ()
454
455(range->vector (range 2 (lambda (i) (not (zero? i))))) ⇑ #(#f #t)
456
457(range->string (range 5 (lambda (i) (integer->char (+ 65 i)))))
458  ⇑ "ABCDE"
459</enscript>
460
461<procedure>(vector->range vector)</procedure>
462
463Returns an expanded range whose elements are those of vector. Note that, unlike vector-range, it is not an error to mutate vector; future mutations of vector are guaranteed not to affect the range returned by vector->range. This procedure must run in O(n) where {{n}} is the length of vector. Otherwise, this procedure is equivalent to vector-range.
464====== Example
465<enscript highlight="scheme">
466(range->list (vector->range #(1 3 5 7 9))) ⇑ (1 3 5 7 9)
467</enscript>
468
469<procedure>(range->generator range)</procedure>
470
471Returns a SRFI 158 generator that generates the elements of range in order. This procedure must run in O(1) time, and the running time of each call of the generator is asymptotically bounded by the average accessing time of range.
472====== Example
473<enscript highlight="scheme">
474(generator->list (range->generator (numeric-range 0 10)))
475  ⇑ (0 1 2 3 4 5 6 7 8 9)
476</enscript>
477=== Implementation
478The sample implementation is in the repository of this SRFI and in this .tgz file. An R7RS library file and a separate file containing the actual implementation are provided, along with a test file that works with SRFI 78, but is self-contained if SRFI 78 does not exist. The implementation uses SRFI 1 and can take advantage of SRFI 145 (assume) if it is present.
479=== Acknowledgements
480Without Python's range object, this SRFI would not exist. Thanks also to the contributors on the SRFI 196 mailing list.
481
482Special thanks to Marc Nieper-Wißkirchen, who provided extensive feedback and invaluable insights during the development of this SRFI.
483=== Author
484==== by John Cowan (text), Wolfgang Corcoran-Mathe (implementation)
485==== Ported to Chicken Scheme 5 by Sergey Goldgaber
486=== Version history
487==== 0.1 - Ported to Chicken Scheme 5
488=== Copyright
489© 2020 John Cowan, Wolfgang Corcoran-Mathe.
490
491Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
492
493The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
494
495THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Note: See TracBrowser for help on using the repository browser.