1 ! Copyright (C) 2004 Chris Double.
2 ! See http://factorcode.org/license.txt for BSD license.
4 ! Updated by Matthew Willis, July 2006
5 ! Updated by Chris Double, September 2006
6 ! Updated by James Cash, June 2008
8 USING: kernel sequences math vectors arrays namespaces
9 quotations promises combinators io lists accessors ;
12 M: promise car ( promise -- car )
15 M: promise cdr ( promise -- cdr )
18 M: promise nil? ( cons -- bool )
21 ! Both 'car' and 'cdr' are promises
22 TUPLE: lazy-cons car cdr ;
24 : lazy-cons ( car cdr -- promise )
25 [ promise ] bi@ \ lazy-cons boa
26 T{ promise f f t f } clone
27 [ set-promise-value ] keep ;
29 M: lazy-cons car ( lazy-cons -- car )
32 M: lazy-cons cdr ( lazy-cons -- cdr )
35 M: lazy-cons nil? ( lazy-cons -- bool )
38 : 1lazy-list ( a -- lazy-cons )
41 : 2lazy-list ( a b -- lazy-cons )
42 1lazy-list 1quotation lazy-cons ;
44 : 3lazy-list ( a b c -- lazy-cons )
45 2lazy-list 1quotation lazy-cons ;
47 : lnth ( n list -- elt )
48 swap [ cdr ] times car ;
50 : (llength) ( list acc -- n )
51 over nil? [ nip ] [ [ cdr ] dip 1+ (llength) ] if ;
53 : llength ( list -- n )
56 : leach ( list quot -- )
57 over nil? [ 2drop ] [ [ uncons ] dip tuck call leach ] if ; inline
59 : lreduce ( list identity quot -- result )
62 TUPLE: memoized-cons original car cdr nil? ;
64 : not-memoized ( -- obj )
67 : not-memoized? ( obj -- bool )
70 : <memoized-cons> ( cons -- memoized-cons )
71 not-memoized not-memoized not-memoized
74 M: memoized-cons car ( memoized-cons -- car )
75 dup car>> not-memoized? [
76 dup original>> car [ >>car drop ] keep
81 M: memoized-cons cdr ( memoized-cons -- cdr )
82 dup cdr>> not-memoized? [
83 dup original>> cdr [ >>cdr drop ] keep
88 M: memoized-cons nil? ( memoized-cons -- bool )
89 dup nil?>> not-memoized? [
90 dup original>> nil? [ >>nil? drop ] keep
95 TUPLE: lazy-map cons quot ;
97 C: <lazy-map> lazy-map
99 : lmap ( list quot -- result )
100 over nil? [ 2drop nil ] [ <lazy-map> <memoized-cons> ] if ;
102 M: lazy-map car ( lazy-map -- car )
106 M: lazy-map cdr ( lazy-map -- cdr )
110 M: lazy-map nil? ( lazy-map -- bool )
113 : lmap-with ( value list quot -- result )
116 TUPLE: lazy-take n cons ;
118 C: <lazy-take> lazy-take
120 : ltake ( n list -- result )
121 over zero? [ 2drop nil ] [ <lazy-take> ] if ;
123 M: lazy-take car ( lazy-take -- car )
126 M: lazy-take cdr ( lazy-take -- cdr )
130 M: lazy-take nil? ( lazy-take -- bool )
137 TUPLE: lazy-until cons quot ;
139 C: <lazy-until> lazy-until
141 : luntil ( list quot -- result )
142 over nil? [ drop ] [ <lazy-until> ] if ;
144 M: lazy-until car ( lazy-until -- car )
147 M: lazy-until cdr ( lazy-until -- cdr )
148 [ cons>> uncons ] keep quot>> tuck call
149 [ 2drop nil ] [ luntil ] if ;
151 M: lazy-until nil? ( lazy-until -- bool )
154 TUPLE: lazy-while cons quot ;
156 C: <lazy-while> lazy-while
158 : lwhile ( list quot -- result )
159 over nil? [ drop ] [ <lazy-while> ] if ;
161 M: lazy-while car ( lazy-while -- car )
164 M: lazy-while cdr ( lazy-while -- cdr )
165 [ cons>> cdr ] keep quot>> lwhile ;
167 M: lazy-while nil? ( lazy-while -- bool )
168 [ car ] keep quot>> call not ;
170 TUPLE: lazy-filter cons quot ;
172 C: <lazy-filter> lazy-filter
174 : lfilter ( list quot -- result )
175 over nil? [ 2drop nil ] [ <lazy-filter> <memoized-cons> ] if ;
177 : car-filter? ( lazy-filter -- ? )
181 : skip ( lazy-filter -- )
182 dup cons>> cdr >>cons ;
184 M: lazy-filter car ( lazy-filter -- car )
185 dup car-filter? [ cons>> ] [ dup skip ] if car ;
187 M: lazy-filter cdr ( lazy-filter -- cdr )
195 M: lazy-filter nil? ( lazy-filter -- bool )
206 : list>vector ( list -- vector )
207 [ [ , ] leach ] V{ } make ;
209 : list>array ( list -- array )
210 [ [ , ] leach ] { } make ;
212 TUPLE: lazy-append list1 list2 ;
214 C: <lazy-append> lazy-append
216 : lappend ( list1 list2 -- result )
217 over nil? [ nip ] [ <lazy-append> ] if ;
219 M: lazy-append car ( lazy-append -- car )
222 M: lazy-append cdr ( lazy-append -- cdr )
226 M: lazy-append nil? ( lazy-append -- bool )
229 TUPLE: lazy-from-by n quot ;
231 C: lfrom-by lazy-from-by ( n quot -- list )
233 : lfrom ( n -- list )
236 M: lazy-from-by car ( lazy-from-by -- car )
239 M: lazy-from-by cdr ( lazy-from-by -- cdr )
241 quot>> dup slip lfrom-by ;
243 M: lazy-from-by nil? ( lazy-from-by -- bool )
246 TUPLE: lazy-zip list1 list2 ;
248 C: <lazy-zip> lazy-zip
250 : lzip ( list1 list2 -- lazy-zip )
251 over nil? over nil? or
252 [ 2drop nil ] [ <lazy-zip> ] if ;
254 M: lazy-zip car ( lazy-zip -- car )
255 [ list1>> car ] keep list2>> car 2array ;
257 M: lazy-zip cdr ( lazy-zip -- cdr )
258 [ list1>> cdr ] keep list2>> cdr lzip ;
260 M: lazy-zip nil? ( lazy-zip -- bool )
263 TUPLE: sequence-cons index seq ;
265 C: <sequence-cons> sequence-cons
267 : seq>list ( index seq -- list )
274 M: sequence-cons car ( sequence-cons -- car )
278 M: sequence-cons cdr ( sequence-cons -- cdr )
282 M: sequence-cons nil? ( sequence-cons -- bool )
285 : >list ( object -- list )
287 { [ dup sequence? ] [ 0 swap seq>list ] }
288 { [ dup list? ] [ ] }
289 [ "Could not convert object to a list" throw ]
292 TUPLE: lazy-concat car cdr ;
294 C: <lazy-concat> lazy-concat
298 : (lconcat) ( car cdr -- list )
305 : lconcat ( list -- result )
309 uncons swap (lconcat)
312 M: lazy-concat car ( lazy-concat -- car )
315 M: lazy-concat cdr ( lazy-concat -- cdr )
316 [ car>> cdr ] keep cdr>> (lconcat) ;
318 M: lazy-concat nil? ( lazy-concat -- bool )
325 : lcartesian-product ( list1 list2 -- result )
326 swap [ swap [ 2array ] lmap-with ] lmap-with lconcat ;
328 : lcartesian-product* ( lists -- result )
332 [ car ] keep cdr [ car lcartesian-product ] keep cdr list>array swap [
333 swap [ swap [ suffix ] lmap-with ] lmap-with lconcat
337 : lcomp ( list quot -- result )
338 [ lcartesian-product* ] dip lmap ;
340 : lcomp* ( list guards quot -- result )
341 [ [ lcartesian-product* ] dip [ lfilter ] each ] dip lmap ;
345 : (lmerge) ( list1 list2 -- result )
346 over [ car ] curry -rot
348 dup [ car ] curry -rot
354 : lmerge ( list1 list2 -- result )
356 { [ over nil? ] [ nip ] }
357 { [ dup nil? ] [ drop ] }
358 { [ t ] [ (lmerge) ] }
361 TUPLE: lazy-io stream car cdr quot ;
365 : lcontents ( stream -- result )
366 f f [ stream-read1 ] <lazy-io> ;
368 : llines ( stream -- result )
369 f f [ stream-readln ] <lazy-io> ;
371 M: lazy-io car ( lazy-io -- car )
375 drop dup stream>> over quot>> call
376 swap dupd set-lazy-io-car
379 M: lazy-io cdr ( lazy-io -- cdr )
387 [ f f ] dip <lazy-io> [ >>cdr drop ] keep
393 M: lazy-io nil? ( lazy-io -- bool )
396 INSTANCE: sequence-cons list
397 INSTANCE: memoized-cons list
398 INSTANCE: promise list
399 INSTANCE: lazy-io list
400 INSTANCE: lazy-concat list
401 INSTANCE: lazy-cons list
402 INSTANCE: lazy-map list
403 INSTANCE: lazy-take list
404 INSTANCE: lazy-append list
405 INSTANCE: lazy-from-by list
406 INSTANCE: lazy-zip list
407 INSTANCE: lazy-while list
408 INSTANCE: lazy-until list
409 INSTANCE: lazy-filter list