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
7 USING: kernel sequences math vectors arrays namespaces generic errors ;
11 GENERIC: car ( cons -- car )
12 GENERIC: cdr ( cons -- cdr )
13 GENERIC: nil? ( cons -- bool )
14 GENERIC: list? ( object -- bool )
16 TUPLE: promise quot forced? value ;
18 C: promise ( quot -- promise ) [ set-promise-quot ] keep ;
20 : promise ( quot -- promise )
23 : promise-with ( value quot -- promise )
26 : promise-with2 ( value1 value2 quot -- promise )
27 curry curry <promise> ;
29 : force ( promise -- value )
30 #! Force the given promise leaving the value of calling the
31 #! promises quotation on the stack. Re-forcing the promise
32 #! will return the same value and not recall the quotation.
34 dup promise-quot call over set-promise-value
35 t over set-promise-forced?
39 M: promise car ( promise -- car )
42 M: promise cdr ( promise -- cdr )
45 M: promise nil? ( cons -- bool )
48 M: promise list? ( object -- bool )
53 M: object list? ( object -- bool )
56 C: cons ( car cdr -- list )
58 [ set-cons-car ] keep ;
60 M: cons car ( cons -- car )
63 M: cons cdr ( cons -- cdr )
69 M: cons nil? ( cons -- bool )
72 M: cons list? ( object -- bool )
75 : cons ( car cdr -- list )
78 : 1list ( obj -- cons )
81 : 2list ( a b -- cons )
84 : 3list ( a b c -- cons )
85 nil <cons> <cons> <cons> ;
87 ! Both 'car' and 'cdr' are promises
88 TUPLE: lazy-cons car cdr ;
90 : lazy-cons ( car cdr -- promise )
91 >r promise r> promise <lazy-cons>
92 T{ promise f f t f } clone [ set-promise-value ] keep ;
94 M: lazy-cons car ( lazy-cons -- car )
97 M: lazy-cons cdr ( lazy-cons -- cdr )
100 M: lazy-cons nil? ( lazy-cons -- bool )
103 M: lazy-cons list? ( object -- bool )
110 : 1lazy-list ( a -- lazy-cons )
113 : 2lazy-list ( a b -- lazy-cons )
114 1lazy-list unit lazy-cons ;
116 : 3lazy-list ( a b c -- lazy-cons )
117 2lazy-list unit lazy-cons ;
119 : lnth ( n list -- elt )
120 swap [ cdr ] times car ;
122 : uncons ( cons -- car cdr )
123 #! Return the car and cdr of the lazy list
126 : leach ( list quot -- )
130 uncons swap pick call swap leach
133 : 2curry ( a b quot -- quot )
136 TUPLE: memoized-cons original car cdr nil? ;
138 : not-memoized ( -- obj )
141 : not-memoized? ( obj -- bool )
144 C: memoized-cons ( cons -- memoized-cons )
145 [ set-memoized-cons-original ] keep
146 not-memoized over set-memoized-cons-car
147 not-memoized over set-memoized-cons-cdr
148 not-memoized over set-memoized-cons-nil? ;
150 M: memoized-cons car ( memoized-cons -- car )
151 dup memoized-cons-car not-memoized? [
152 dup memoized-cons-original car [ swap set-memoized-cons-car ] keep
157 M: memoized-cons cdr ( memoized-cons -- cdr )
158 dup memoized-cons-cdr not-memoized? [
159 dup memoized-cons-original cdr [ swap set-memoized-cons-cdr ] keep
164 M: memoized-cons nil? ( memoized-cons -- bool )
165 dup memoized-cons-nil? not-memoized? [
166 dup memoized-cons-original nil? [ swap set-memoized-cons-nil? ] keep
171 M: memoized-cons list? ( object -- bool )
174 TUPLE: lazy-map cons quot ;
176 : lmap ( list quot -- result )
177 over nil? [ 2drop nil ] [ <lazy-map> <memoized-cons> ] if ;
179 M: lazy-map car ( lazy-map -- car )
180 [ lazy-map-cons car ] keep
183 M: lazy-map cdr ( lazy-map -- cdr )
184 [ lazy-map-cons cdr ] keep
187 M: lazy-map nil? ( lazy-map -- bool )
190 M: lazy-map list? ( object -- bool )
193 TUPLE: lazy-map-with value cons quot ;
195 : lmap-with ( value list quot -- result )
196 over nil? [ 3drop nil ] [ <lazy-map-with> <memoized-cons> ] if ;
198 M: lazy-map-with car ( lazy-map-with -- car )
199 [ lazy-map-with-value ] keep
200 [ lazy-map-with-cons car ] keep
201 lazy-map-with-quot call ;
203 M: lazy-map-with cdr ( lazy-map-with -- cdr )
204 [ lazy-map-with-value ] keep
205 [ lazy-map-with-cons cdr ] keep
206 lazy-map-with-quot lmap-with ;
208 M: lazy-map-with nil? ( lazy-map-with -- bool )
209 lazy-map-with-cons nil? ;
211 M: lazy-map-with list? ( object -- bool )
214 TUPLE: lazy-take n cons ;
216 : ltake ( n list -- result )
217 over zero? [ 2drop nil ] [ <lazy-take> ] if ;
219 M: lazy-take car ( lazy-take -- car )
222 M: lazy-take cdr ( lazy-take -- cdr )
223 [ lazy-take-n 1- ] keep
224 lazy-take-cons cdr ltake ;
226 M: lazy-take nil? ( lazy-take -- bool )
227 dup lazy-take-n zero? [
233 M: lazy-take list? ( object -- bool )
236 TUPLE: lazy-subset cons quot ;
238 : lsubset ( list quot -- list )
239 over nil? [ 2drop nil ] [ <lazy-subset> <memoized-cons> ] if ;
241 : car-subset? ( lazy-subset -- )
242 [ lazy-subset-cons car ] keep
243 lazy-subset-quot call ;
245 : skip ( lazy-subset -- )
246 [ lazy-subset-cons cdr ] keep
247 set-lazy-subset-cons ;
249 M: lazy-subset car ( lazy-subset -- car )
256 M: lazy-subset cdr ( lazy-subset -- cdr )
258 [ lazy-subset-cons cdr ] keep
259 lazy-subset-quot lsubset
264 M: lazy-subset nil? ( lazy-subset -- bool )
265 dup lazy-subset-cons nil? [
275 M: lazy-subset list? ( object -- bool )
278 : list>vector ( list -- vector )
279 [ [ , ] leach ] V{ } make ;
281 : list>array ( list -- array )
282 [ [ , ] leach ] { } make ;
284 TUPLE: lazy-append list1 list2 ;
286 : lappend ( list1 list2 -- result )
288 { [ over nil? ] [ nip ] }
289 { [ t ] [ <lazy-append> ] }
292 M: lazy-append car ( lazy-append -- car )
293 lazy-append-list1 car ;
295 M: lazy-append cdr ( lazy-append -- cdr )
296 [ lazy-append-list1 cdr ] keep
297 lazy-append-list2 lappend ;
299 M: lazy-append nil? ( lazy-append -- bool )
300 dup lazy-append-list1 nil? [
301 lazy-append-list2 nil?
306 M: lazy-append list? ( object -- bool )
309 TUPLE: lazy-from-by n quot ;
311 : lfrom-by ( n quot -- list )
314 : lfrom ( n -- list )
317 M: lazy-from-by car ( lazy-from-by -- car )
320 M: lazy-from-by cdr ( lazy-from-by -- cdr )
321 [ lazy-from-by-n ] keep
322 lazy-from-by-quot dup >r call r> lfrom-by ;
324 M: lazy-from-by nil? ( lazy-from-by -- bool )
327 M: lazy-from-by list? ( object -- bool )
330 TUPLE: lazy-zip list1 list2 ;
332 : lzip ( list1 list2 -- lazy-zip )
333 over nil? over nil? or
334 [ 2drop nil ] [ <lazy-zip> ] if ;
336 M: lazy-zip car ( lazy-zip -- car )
337 [ lazy-zip-list1 car ] keep lazy-zip-list2 car 2array ;
339 M: lazy-zip cdr ( lazy-zip -- cdr )
340 [ lazy-zip-list1 cdr ] keep lazy-zip-list2 cdr lzip ;
342 M: lazy-zip nil? ( lazy-zip -- bool )
345 M: lazy-zip list? ( object -- bool )
348 TUPLE: sequence-cons index seq ;
350 : seq>list ( index seq -- list )
357 M: sequence-cons car ( sequence-cons -- car )
358 [ sequence-cons-index ] keep
359 sequence-cons-seq nth ;
361 M: sequence-cons cdr ( sequence-cons -- cdr )
362 [ sequence-cons-index 1+ ] keep
363 sequence-cons-seq seq>list ;
365 M: sequence-cons nil? ( sequence-cons -- bool )
368 M: sequence-cons list? ( object -- bool )
371 : >list ( object -- list )
373 { [ dup sequence? ] [ 0 swap seq>list ] }
374 { [ dup list? ] [ ] }
375 { [ t ] [ "Could not convert object to a list" throw ] }
378 TUPLE: lazy-concat car cdr ;
382 : (lconcat) ( car cdr -- list )
389 : lconcat ( list -- list )
396 M: lazy-concat car ( lazy-concat -- car )
397 lazy-concat-car car ;
399 M: lazy-concat cdr ( lazy-concat -- cdr )
400 [ lazy-concat-car cdr ] keep lazy-concat-cdr (lconcat) ;
402 M: lazy-concat nil? ( lazy-concat -- bool )
403 dup lazy-concat-car nil? [
409 M: lazy-concat list? ( object -- bool )
412 : lcartesian-product ( list1 list2 -- result )
413 swap [ swap [ 2array ] lmap-with ] lmap-with lconcat ;
415 : lcartesian-product* ( lists -- result )
419 [ car ] keep cdr [ car lcartesian-product ] keep cdr list>array swap [
420 swap [ swap [ add ] lmap-with ] lmap-with lconcat
424 : lcomp ( list quot -- result )
425 >r lcartesian-product* r> lmap ;
427 : lcomp* ( list guards quot -- result )
428 >r >r lcartesian-product* r> [ lsubset ] each r> lmap ;
432 : (lmerge) ( list1 list2 -- result )
433 over [ car ] curry -rot
435 dup [ car ] curry -rot
438 ] curry curry lazy-cons
439 ] curry curry lazy-cons ;
441 : lmerge ( list1 list2 -- result )
443 { [ over nil? ] [ nip ] }
444 { [ dup nil? ] [ drop ] }
445 { [ t ] [ (lmerge) ] }