]> gitweb.factorcode.org Git - factor.git/blobdiff - basis/lists/lazy/lazy.factor
factor: trim using lists
[factor.git] / basis / lists / lazy / lazy.factor
index 49aee471bf8f407feabc8f6cc6757d3f0c12515f..3209ab657559e2db04ad477fa842a1e72428172e 100644 (file)
@@ -1,34 +1,28 @@
 ! Copyright (C) 2004, 2008 Chris Double, Matthew Willis, James Cash.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel sequences math vectors arrays namespaces make
-quotations promises combinators io lists accessors ;
+USING: accessors arrays combinators io kernel lists math
+promises quotations sequences ;
 IN: lists.lazy
 
-M: promise car ( promise -- car )
-    force car ;
+M: promise car force car ;
 
-M: promise cdr ( promise -- cdr )
-    force cdr ;
+M: promise cdr force cdr ;
 
-M: promise nil? ( cons -- bool )
-    force nil? ;
-    
-! Both 'car' and 'cdr' are promises
-TUPLE: lazy-cons car cdr ;
+M: promise nil? force nil? ;
+
+TUPLE: lazy-cons-state { car promise } { cdr promise } ;
+
+C: <lazy-cons-state> lazy-cons-state
 
 : lazy-cons ( car cdr -- promise )
-    [ promise ] bi@ \ lazy-cons boa
-    T{ promise f f t f } clone
-        swap >>value ;
+    [ <promise> ] bi@ <lazy-cons-state>
+    [ f t ] dip promise boa ;
 
-M: lazy-cons car ( lazy-cons -- car )
-    car>> force ;
+M: lazy-cons-state car car>> force ;
 
-M: lazy-cons cdr ( lazy-cons -- cdr )
-    cdr>> force ;
+M: lazy-cons-state cdr cdr>> force ;
 
-M: lazy-cons nil? ( lazy-cons -- bool )
-    nil eq? ;
+M: lazy-cons-state nil? car nil? ;
 
 : 1lazy-list ( a -- lazy-cons )
     [ nil ] lazy-cons ;
@@ -41,33 +35,29 @@ M: lazy-cons nil? ( lazy-cons -- bool )
 
 TUPLE: memoized-cons original car cdr nil? ;
 
-: not-memoized ( -- obj )
-    { } ;
-
-: not-memoized? ( obj -- bool )
-    not-memoized eq? ;
+SYMBOL: +not-memoized+
 
 : <memoized-cons> ( cons -- memoized-cons )
-    not-memoized not-memoized not-memoized
+    +not-memoized+ +not-memoized+ +not-memoized+
     memoized-cons boa ;
 
-M: memoized-cons car ( memoized-cons -- car )
-    dup car>> not-memoized? [
+M: memoized-cons car
+    dup car>> +not-memoized+ eq? [
         dup original>> car [ >>car drop ] keep
     ] [
         car>>
     ] if ;
 
-M: memoized-cons cdr ( memoized-cons -- cdr )
-    dup cdr>> not-memoized? [
+M: memoized-cons cdr
+    dup cdr>> +not-memoized+ eq? [
         dup original>> cdr [ >>cdr drop ] keep
     ] [
         cdr>>
     ] if ;
 
-M: memoized-cons nil? ( memoized-cons -- bool )
-    dup nil?>> not-memoized? [
-        dup original>> nil?  [ >>nil? drop ] keep
+M: memoized-cons nil?
+    dup nil?>> +not-memoized+ eq? [
+        dup original>> nil? [ >>nil? drop ] keep
     ] [
         nil?>>
     ] if ;
@@ -76,18 +66,16 @@ TUPLE: lazy-map cons quot ;
 
 C: <lazy-map> lazy-map
 
-: lazy-map ( list quot -- result )
+: lmap-lazy ( list quot -- result )
     over nil? [ 2drop nil ] [ <lazy-map> <memoized-cons> ] if ;
 
-M: lazy-map car ( lazy-map -- car )
-    [ cons>> car ] keep
-    quot>> call( old -- new ) ;
+M: lazy-map car
+    [ cons>> car ] [ quot>> call( old -- new ) ] bi ;
 
-M: lazy-map cdr ( lazy-map -- cdr )
-    [ cons>> cdr ] keep
-    quot>> lazy-map ;
+M: lazy-map cdr
+    [ cons>> cdr ] [ quot>> lmap-lazy ] bi ;
 
-M: lazy-map nil? ( lazy-map -- bool )
+M: lazy-map nil?
     cons>> nil? ;
 
 TUPLE: lazy-take n cons ;
@@ -95,168 +83,155 @@ TUPLE: lazy-take n cons ;
 C: <lazy-take> lazy-take
 
 : ltake ( n list -- result )
-        over zero? [ 2drop nil ] [ <lazy-take> ] if ;
+    over zero? [ 2drop nil ] [ <lazy-take> ] if ;
 
-M: lazy-take car ( lazy-take -- car )
+M: lazy-take car
     cons>> car ;
 
-M: lazy-take cdr ( lazy-take -- cdr )
-    [ n>> 1- ] keep
-    cons>> cdr ltake ;
+M: lazy-take cdr
+    [ n>> 1 - ] [ cons>> cdr ltake ] bi ;
 
-M: lazy-take nil? ( lazy-take -- bool )
-    dup n>> zero? [
-        drop t
-    ] [
-        cons>> nil?
-    ] if ;
+M: lazy-take nil?
+    dup n>> zero? [ drop t ] [ cons>> nil? ] if ;
 
 TUPLE: lazy-until cons quot ;
 
 C: <lazy-until> lazy-until
 
-: luntil ( list quot -- result )
+: luntil ( list quot: ( elt -- ? ) -- result )
     over nil? [ drop ] [ <lazy-until> ] if ;
 
-M: lazy-until car ( lazy-until -- car )
-     cons>> car ;
+M: lazy-until car
+    cons>> car ;
 
-M: lazy-until cdr ( lazy-until -- cdr )
-     [ cons>> unswons ] keep quot>> tuck call( elt -- ? )
-     [ 2drop nil ] [ luntil ] if ;
+M: lazy-until cdr
+    [ [ cons>> cdr ] [ quot>> ] bi ]
+    [ [ cons>> car ] [ quot>> ] bi call( elt -- ? ) ] bi
+    [ 2drop nil ] [ luntil ] if ;
 
-M: lazy-until nil? ( lazy-until -- bool )
-     drop f ;
+M: lazy-until nil?
+    drop f ;
 
 TUPLE: lazy-while cons quot ;
 
 C: <lazy-while> lazy-while
 
-: lwhile ( list quot -- result )
+: lwhile ( list quot: ( elt -- ? ) -- result )
     over nil? [ drop ] [ <lazy-while> ] if ;
 
-M: lazy-while car ( lazy-while -- car )
-     cons>> car ;
+M: lazy-while car
+    cons>> car ;
 
-M: lazy-while cdr ( lazy-while -- cdr )
-     [ cons>> cdr ] keep quot>> lwhile ;
+M: lazy-while cdr
+    [ cons>> cdr ] keep quot>> lwhile ;
 
-M: lazy-while nil? ( lazy-while -- bool )
-     [ car ] keep quot>> call( elt -- ? ) not ;
+M: lazy-while nil?
+    [ car ] keep quot>> call( elt -- ? ) not ;
 
 TUPLE: lazy-filter cons quot ;
 
 C: <lazy-filter> lazy-filter
 
-: lfilter ( list quot -- result )
+: lfilter ( list quot: ( elt -- ? ) -- result )
     over nil? [ 2drop nil ] [ <lazy-filter> <memoized-cons> ] if ;
 
-: car-filter? ( lazy-filter -- ? )
+<PRIVATE
+
+: car-filtered? ( lazy-filter -- ? )
     [ cons>> car ] [ quot>> ] bi call( elt -- ? ) ;
 
-: skip ( lazy-filter -- )
-    dup cons>> cdr >>cons drop ;
+: skip ( lazy-filter -- lazy-filter )
+    [ cdr ] change-cons ;
+
+PRIVATE>
 
-M: lazy-filter car ( lazy-filter -- car )
-    dup car-filter? [ cons>> ] [ dup skip ] if car ;
+M: lazy-filter car
+    dup car-filtered? [ cons>> ] [ skip ] if car ;
 
-M: lazy-filter cdr ( lazy-filter -- cdr )
-    dup car-filter? [
+M: lazy-filter cdr
+    dup car-filtered? [
         [ cons>> cdr ] [ quot>> ] bi lfilter
     ] [
-        dup skip cdr
+        skip cdr
     ] if ;
 
-M: lazy-filter nil? ( lazy-filter -- bool )
-    dup cons>> nil? [
-        drop t
-    ] [
-        dup car-filter? [
-            drop f
-        ] [
-            dup skip nil?
-        ] if
-    ] if ;
+M: lazy-filter nil?
+    {
+        { [ dup cons>> nil? ] [ drop t ] }
+        { [ dup car-filtered? ] [ drop f ] }
+        [ skip nil? ]
+    } cond ;
 
 TUPLE: lazy-append list1 list2 ;
 
 C: <lazy-append> lazy-append
 
-: lappend ( list1 list2 -- result )
+: lappend-lazy ( list1 list2 -- result )
     over nil? [ nip ] [ <lazy-append> ] if ;
 
-M: lazy-append car ( lazy-append -- car )
+M: lazy-append car
     list1>> car ;
 
-M: lazy-append cdr ( lazy-append -- cdr )
-    [ list1>> cdr    ] keep
-    list2>> lappend ;
+M: lazy-append cdr
+    [ list1>> cdr ] [ list2>> ] bi lappend-lazy ;
 
-M: lazy-append nil? ( lazy-append -- bool )
+M: lazy-append nil?
      drop f ;
 
 TUPLE: lazy-from-by n quot ;
 
-C: lfrom-by lazy-from-by
+: lfrom-by ( n quot: ( n -- o ) -- result ) lazy-from-by boa ; inline
 
-: lfrom ( n -- list )
-    [ 1+ ] lfrom-by ;
+: lfrom ( n -- result )
+    [ 1 + ] lfrom-by ;
 
-M: lazy-from-by car ( lazy-from-by -- car )
+M: lazy-from-by car
     n>> ;
 
-M: lazy-from-by cdr ( lazy-from-by -- cdr )
-    [ n>> ] keep
-    quot>> [ call( old -- new ) ] keep lfrom-by ;
+M: lazy-from-by cdr
+    [ n>> ] [ quot>> ] bi [ call( old -- new ) ] keep lfrom-by ;
 
-M: lazy-from-by nil? ( lazy-from-by -- bool )
+M: lazy-from-by nil?
     drop f ;
 
 TUPLE: lazy-zip list1 list2 ;
 
 C: <lazy-zip> lazy-zip
 
-: lzip ( list1 list2 -- lazy-zip )
-        over nil? over nil? or
-        [ 2drop nil ] [ <lazy-zip> ] if ;
+: lzip ( list1 list2 -- result )
+    2dup [ nil? ] either?
+    [ 2drop nil ] [ <lazy-zip> ] if ;
 
-M: lazy-zip car ( lazy-zip -- car )
-        [ list1>> car ] keep list2>> car 2array ;
+M: lazy-zip car
+    [ list1>> car ] keep list2>> car 2array ;
 
-M: lazy-zip cdr ( lazy-zip -- cdr )
-        [ list1>> cdr ] keep list2>> cdr lzip ;
+M: lazy-zip cdr
+    [ list1>> cdr ] keep list2>> cdr lzip ;
 
-M: lazy-zip nil? ( lazy-zip -- bool )
-        drop f ;
+M: lazy-zip nil?
+    drop f ;
 
 TUPLE: sequence-cons index seq ;
 
 C: <sequence-cons> sequence-cons
 
-: seq>list ( index seq -- list )
+: sequence-tail>list ( index seq -- list )
     2dup length >= [
         2drop nil
     ] [
         <sequence-cons>
     ] if ;
 
-M: sequence-cons car ( sequence-cons -- car )
-    [ index>> ] keep
-    seq>> nth ;
+M: sequence-cons car
+    [ index>> ] [ seq>> nth ] bi ;
 
-M: sequence-cons cdr ( sequence-cons -- cdr )
-    [ index>> 1+ ] keep
-    seq>> seq>list ;
+M: sequence-cons cdr
+    [ index>> 1 + ] [ seq>> sequence-tail>list ] bi ;
 
-M: sequence-cons nil? ( sequence-cons -- bool )
+M: sequence-cons nil?
     drop f ;
 
-: >list ( object -- list )
-    {
-        { [ dup sequence? ] [ 0 swap seq>list ] }
-        { [ dup list?         ] [ ] }
-        [ "Could not convert object to a list" throw ]
-    } cond ;
+M: sequence >list 0 swap sequence-tail>list ;
 
 TUPLE: lazy-concat car cdr ;
 
@@ -264,67 +239,65 @@ C: <lazy-concat> lazy-concat
 
 DEFER: lconcat
 
+<PRIVATE
+
 : (lconcat) ( car cdr -- list )
-    over nil? [
-        nip lconcat
-    ] [
-        <lazy-concat>
-    ] if ;
+    over nil? [ nip lconcat ] [ <lazy-concat> ] if ;
+
+PRIVATE>
 
 : lconcat ( list -- result )
-    dup nil? [
-        drop nil
-    ] [
-        uncons (lconcat)
-    ] if ;
+    dup nil? [ drop nil ] [ uncons (lconcat) ] if ;
 
-M: lazy-concat car ( lazy-concat -- car )
+M: lazy-concat car
     car>> car ;
 
-M: lazy-concat cdr ( lazy-concat -- cdr )
+M: lazy-concat cdr
     [ car>> cdr ] keep cdr>> (lconcat) ;
 
-M: lazy-concat nil? ( lazy-concat -- bool )
-    dup car>> nil? [
-        cdr>> nil?
-    ] [
-        drop f
-    ] if ;
+M: lazy-concat nil?
+    dup car>> nil? [ cdr>> nil?  ] [ drop f ] if ;
 
 : lcartesian-product ( list1 list2 -- result )
-    swap [ swap [ 2array ] with lazy-map  ] with lazy-map  lconcat ;
+    swap [ swap [ 2array ] with lmap-lazy ] with lmap-lazy lconcat ;
 
 : lcartesian-product* ( lists -- result )
     dup nil? [
         drop nil
     ] [
-        [ car ] keep cdr [ car lcartesian-product ] keep cdr list>array swap [
-            swap [ swap [ suffix ] with lazy-map  ] with lazy-map  lconcat
+        uncons
+        [ car lcartesian-product ] [ cdr ] bi
+        list>array swap [
+            swap [ swap [ suffix ] with lmap-lazy ] with lmap-lazy lconcat
         ] reduce
     ] if ;
 
-: lcomp ( list quot -- result )
-    [ lcartesian-product* ] dip lazy-map ;
+: lcartesian-map ( list quot: ( elt1 elt2 -- newelt ) -- result )
+    [ lcartesian-product* ] dip [ first2 ] prepose lmap-lazy ;
 
-: lcomp* ( list guards quot -- result )
-    [ [ lcartesian-product* ] dip [ lfilter ] each ] dip lazy-map ;
+: lcartesian-map* ( list guards quot: ( elt1 elt2 -- newelt ) -- result )
+    [ [ [ first2 ] prepose ] map ] [ [ first2 ] prepose ] bi*
+    [ [ lcartesian-product* ] dip [ lfilter ] each ] dip lmap-lazy ;
 
 DEFER: lmerge
 
-: (lmerge) ( list1 list2 -- result )
-    over [ car ] curry -rot
+<PRIVATE
+
+:: (lmerge) ( list1 list2 -- result )
+    [ list1 car ]
     [
-        dup [ car ] curry -rot
-        [
-            [ cdr ] bi@ lmerge
-        ] 2curry lazy-cons
-    ] 2curry lazy-cons ;
+        [ list2 car ]
+        [ list1 cdr list2 cdr lmerge ]
+        lazy-cons
+    ] lazy-cons ;
+
+PRIVATE>
 
 : lmerge ( list1 list2 -- result )
     {
-        { [ over nil? ] [ nip     ] }
-        { [ dup nil?    ]    [ drop ] }
-        { [ t                 ]    [ (lmerge) ] }
+        { [ over nil? ] [ nip ] }
+        { [ dup nil? ] [ drop ] }
+        [ (lmerge) ]
     } cond ;
 
 TUPLE: lazy-io stream car cdr quot ;
@@ -337,38 +310,35 @@ C: <lazy-io> lazy-io
 : llines ( stream -- result )
     f f [ stream-readln ] <lazy-io> ;
 
-M: lazy-io car ( lazy-io -- car )
-    dup car>> dup [
+M: lazy-io car
+    dup car>> [
         nip
     ] [
-        drop dup stream>> over quot>>
-        call( stream -- value )
-        >>car
-    ] if ;
+        dup [ stream>> ] [ quot>> ] bi
+        call( stream -- value ) [ >>car ] [ drop nil ] if*
+    ] if* ;
 
-M: lazy-io cdr ( lazy-io -- cdr )
+M: lazy-io cdr
     dup cdr>> dup [
         nip
     ] [
-        drop dup
-        [ stream>> ] keep
-        [ quot>> ] keep
-        car [
+        drop dup [ stream>> ] [ quot>> ] [ car ] tri
+        [
             [ f f ] dip <lazy-io> [ >>cdr drop ] keep
         ] [
             3drop nil
         ] if
     ] if ;
 
-M: lazy-io nil? ( lazy-io -- bool )
-    car not ;
+M: lazy-io nil?
+    car nil? ;
 
 INSTANCE: sequence-cons list
 INSTANCE: memoized-cons list
 INSTANCE: promise list
 INSTANCE: lazy-io list
 INSTANCE: lazy-concat list
-INSTANCE: lazy-cons list
+INSTANCE: lazy-cons-state list
 INSTANCE: lazy-map list
 INSTANCE: lazy-take list
 INSTANCE: lazy-append list