lists: more cleanup.
parent
da65402ee8
commit
0add9190c2
|
@ -23,8 +23,8 @@ ARTICLE: { "lists.lazy" "combinators" } "Combinators for manipulating lazy lists
|
|||
luntil
|
||||
lwhile
|
||||
lfrom-by
|
||||
lcomp
|
||||
lcomp*
|
||||
lcartesian-map
|
||||
lcartesian-map*
|
||||
} ;
|
||||
|
||||
ARTICLE: { "lists.lazy" "io" } "Lazy list I/O"
|
||||
|
@ -82,7 +82,7 @@ HELP: <memoized-cons>
|
|||
{ $description "Constructs a cons object that wraps an existing cons object. Requests for the car, cdr and nil? will be remembered after the first call, and the previous result returned on subsequent calls." }
|
||||
{ $see-also cons car cdr nil nil? } ;
|
||||
|
||||
{ lmap-lazy ltake lfilter lappend-lazy lfrom lfrom-by lconcat lcartesian-product lcartesian-product* lcomp lcomp* lmerge lwhile luntil } related-words
|
||||
{ lmap-lazy ltake lfilter lappend-lazy lfrom lfrom-by lconcat lcartesian-product lcartesian-product* lcartesian-map lcartesian-map* lmerge lwhile luntil } related-words
|
||||
|
||||
HELP: lmap-lazy
|
||||
{ $values { "list" "a cons object" } { "quot" { $quotation ( obj -- X ) } } { "result" "resulting cons object" } }
|
||||
|
@ -93,15 +93,15 @@ HELP: ltake
|
|||
{ $description "Outputs a lazy list containing the first n items in the list. This is done a lazy manner. No evaluation of the list elements occurs initially but a " { $link lazy-take } " object is returned which conforms to the list protocol. Calling " { $link car } ", " { $link cdr } " or " { $link nil? } " on this will evaluate elements as required." } ;
|
||||
|
||||
HELP: lfilter
|
||||
{ $values { "list" "a cons object" } { "quot" { $quotation ( -- X ) } } { "result" "resulting cons object" } }
|
||||
{ $values { "list" "a cons object" } { "quot" { $quotation ( elt -- ? ) } } { "result" "resulting cons object" } }
|
||||
{ $description "Perform a similar functionality to that of the " { $link filter } " word, but in a lazy manner. No evaluation of the list elements occurs initially but a " { $link lazy-filter } " object is returned which conforms to the list protocol. Calling " { $link car } ", " { $link cdr } " or " { $link nil? } " on this will evaluate elements as required." } ;
|
||||
|
||||
HELP: lwhile
|
||||
{ $values { "list" "a cons object" } { "quot" { $quotation ( x -- ? ) } } { "result" "resulting cons object" } }
|
||||
{ $values { "list" "a cons object" } { "quot" { $quotation ( elt -- ? ) } } { "result" "resulting cons object" } }
|
||||
{ $description "Outputs a lazy list containing the first items in the list as long as " { $snippet "quot" } " evaluates to t. No evaluation of the list elements occurs initially but a " { $link lazy-while } " object is returned with conforms to the list protocol. Calling " { $link car } ", " { $link cdr } " or " { $link nil? } " on this will evaluate elements as required." } ;
|
||||
|
||||
HELP: luntil
|
||||
{ $values { "list" "a cons object" } { "quot" { $quotation ( x -- ? ) } } { "result" "resulting cons object" } }
|
||||
{ $values { "list" "a cons object" } { "quot" { $quotation ( elt -- ? ) } } { "result" "resulting cons object" } }
|
||||
{ $description "Outputs a lazy list containing the first items in the list until after " { $snippet "quot" } " evaluates to t. No evaluation of the list elements occurs initially but a " { $link lazy-while } " object is returned with conforms to the list protocol. Calling " { $link car } ", " { $link cdr } " or " { $link nil? } " on this will evaluate elements as required." } ;
|
||||
|
||||
HELP: lappend-lazy
|
||||
|
@ -121,7 +121,7 @@ HELP: sequence-tail>list
|
|||
{ $description "Convert the sequence into a list, starting from " { $snippet "index" } "." }
|
||||
{ $see-also >list } ;
|
||||
|
||||
{ leach foldl lmap-lazy ltake lfilter lappend-lazy lfrom lfrom-by lconcat lcartesian-product lcartesian-product* lcomp lcomp* lmerge lwhile luntil } related-words
|
||||
{ leach foldl lmap-lazy ltake lfilter lappend-lazy lfrom lfrom-by lconcat lcartesian-product lcartesian-product* lcartesian-map lcartesian-map* lmerge lwhile luntil } related-words
|
||||
|
||||
HELP: lconcat
|
||||
{ $values { "list" "a list of lists" } { "result" "a list" } }
|
||||
|
@ -135,15 +135,15 @@ HELP: lcartesian-product*
|
|||
{ $values { "lists" "a list of lists" } { "result" "list of cartesian products" } }
|
||||
{ $description "Given a list of lists, return a list containing the cartesian product of those lists." } ;
|
||||
|
||||
HELP: lcomp
|
||||
{ $values { "list" "a list of lists" } { "quot" { $quotation ( seq -- X ) } } { "result" "the resulting list" } }
|
||||
HELP: lcartesian-map
|
||||
{ $values { "list" "a list of lists" } { "quot" { $quotation ( elt1 elt2 -- newelt ) } } { "result" "the resulting list" } }
|
||||
{ $description "Get the cartesian product of the lists in " { $snippet "list" } " and call " { $snippet "quot" } " call with each element from the cartesian product on the stack, the result of which is returned in the final " { $snippet "list" } "." } ;
|
||||
|
||||
HELP: lcomp*
|
||||
{ $values { "list" "a list of lists" } { "guards" "a sequence of quotations with stack effect ( seq -- bool )" } { "quot" { $quotation ( seq -- X ) } } { "result" "a list" } }
|
||||
HELP: lcartesian-map*
|
||||
{ $values { "list" "a list of lists" } { "guards" "a sequence of quotations with stack effect ( elt1 elt2 -- ? )" } { "quot" { $quotation ( elt1 elt2 -- newelt ) } } { "result" "a list" } }
|
||||
{ $description "Get the cartesian product of the lists in " { $snippet "list" } ", filter it by applying each guard quotation to it and call " { $snippet "quot" } " call with each element from the remaining cartesian product items on the stack, the result of which is returned in the final " { $snippet "list" } "." }
|
||||
{ $examples
|
||||
{ $code "{ 1 2 3 } >list { 4 5 6 } >list 2list { [ first odd? ] } [ first2 + ] lcomp*" }
|
||||
{ $code "{ 1 2 3 } >list { 4 5 6 } >list 2list { [ drop odd? ] } [ + ] lcartesian-map*" }
|
||||
} ;
|
||||
|
||||
HELP: lmerge
|
||||
|
|
|
@ -17,11 +17,11 @@ IN: lists.lazy.tests
|
|||
] unit-test
|
||||
|
||||
{ { 5 6 6 7 7 8 } } [
|
||||
{ 1 2 3 } >list { 4 5 } >list 2list [ first2 + ] lcomp list>array
|
||||
{ 1 2 3 } >list { 4 5 } >list 2list [ + ] lcartesian-map list>array
|
||||
] unit-test
|
||||
|
||||
{ { 5 6 7 8 } } [
|
||||
{ 1 2 3 } >list { 4 5 } >list 2list { [ first odd? ] } [ first2 + ] lcomp* list>array
|
||||
{ 1 2 3 } >list { 4 5 } >list 2list { [ drop odd? ] } [ + ] lcartesian-map* list>array
|
||||
] unit-test
|
||||
|
||||
{ { 4 5 6 } } [
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
! Copyright (C) 2004, 2008 Chris Double, Matthew Willis, James Cash.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: accessors arrays combinators io kernel lists math
|
||||
USING: accessors arrays combinators io kernel lists locals math
|
||||
promises quotations sequences ;
|
||||
IN: lists.lazy
|
||||
|
||||
|
@ -10,9 +10,7 @@ M: promise cdr force cdr ;
|
|||
|
||||
M: promise nil? force nil? ;
|
||||
|
||||
TUPLE: lazy-cons-state
|
||||
{ car promise }
|
||||
{ cdr promise } ;
|
||||
TUPLE: lazy-cons-state { car promise } { cdr promise } ;
|
||||
|
||||
C: <lazy-cons-state> lazy-cons-state
|
||||
|
||||
|
@ -24,7 +22,7 @@ M: lazy-cons-state car car>> force ;
|
|||
|
||||
M: lazy-cons-state cdr cdr>> force ;
|
||||
|
||||
M: lazy-cons-state nil? nil eq? ;
|
||||
M: lazy-cons-state nil? car nil? ;
|
||||
|
||||
: 1lazy-list ( a -- lazy-cons )
|
||||
[ nil ] lazy-cons ;
|
||||
|
@ -100,7 +98,7 @@ 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
|
||||
|
@ -118,7 +116,7 @@ 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
|
||||
|
@ -134,34 +132,34 @@ 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 ;
|
||||
|
||||
<PRIVATE
|
||||
|
||||
: car-filter? ( lazy-filter -- ? )
|
||||
: 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
|
||||
dup car-filter? [ cons>> ] [ dup skip ] if car ;
|
||||
dup car-filtered? [ cons>> ] [ skip ] if car ;
|
||||
|
||||
M: lazy-filter cdr
|
||||
dup car-filter? [
|
||||
dup car-filtered? [
|
||||
[ cons>> cdr ] [ quot>> ] bi lfilter
|
||||
] [
|
||||
dup skip cdr
|
||||
skip cdr
|
||||
] if ;
|
||||
|
||||
M: lazy-filter nil?
|
||||
{
|
||||
{ [ dup cons>> nil? ] [ drop t ] }
|
||||
{ [ dup car-filter? ] [ drop f ] }
|
||||
[ dup skip nil? ]
|
||||
{ [ dup car-filtered? ] [ drop f ] }
|
||||
[ skip nil? ]
|
||||
} cond ;
|
||||
|
||||
TUPLE: lazy-append list1 list2 ;
|
||||
|
@ -182,9 +180,9 @@ M: lazy-append nil?
|
|||
|
||||
TUPLE: lazy-from-by n quot ;
|
||||
|
||||
: lfrom-by ( n quot: ( n -- o ) -- lazy-from-by ) lazy-from-by boa ; inline
|
||||
: lfrom-by ( n quot: ( n -- o ) -- result ) lazy-from-by boa ; inline
|
||||
|
||||
: lfrom ( n -- list )
|
||||
: lfrom ( n -- result )
|
||||
[ 1 + ] lfrom-by ;
|
||||
|
||||
M: lazy-from-by car
|
||||
|
@ -200,8 +198,8 @@ TUPLE: lazy-zip list1 list2 ;
|
|||
|
||||
C: <lazy-zip> lazy-zip
|
||||
|
||||
: lzip ( list1 list2 -- lazy-zip )
|
||||
over nil? over nil? or
|
||||
: lzip ( list1 list2 -- result )
|
||||
2dup [ nil? ] either?
|
||||
[ 2drop nil ] [ <lazy-zip> ] if ;
|
||||
|
||||
M: lazy-zip car
|
||||
|
@ -241,9 +239,13 @@ C: <lazy-concat> lazy-concat
|
|||
|
||||
DEFER: lconcat
|
||||
|
||||
<PRIVATE
|
||||
|
||||
: (lconcat) ( car cdr -- list )
|
||||
over nil? [ nip lconcat ] [ <lazy-concat> ] if ;
|
||||
|
||||
PRIVATE>
|
||||
|
||||
: lconcat ( list -- result )
|
||||
dup nil? [ drop nil ] [ uncons (lconcat) ] if ;
|
||||
|
||||
|
@ -257,7 +259,7 @@ M: lazy-concat nil?
|
|||
dup car>> nil? [ cdr>> nil? ] [ drop f ] if ;
|
||||
|
||||
: lcartesian-product ( list1 list2 -- result )
|
||||
swap [ swap [ 2array ] with lmap-lazy ] with lmap-lazy lconcat ;
|
||||
swap [ swap [ 2array ] with lmap-lazy ] with lmap-lazy lconcat ;
|
||||
|
||||
: lcartesian-product* ( lists -- result )
|
||||
dup nil? [
|
||||
|
@ -270,28 +272,32 @@ M: lazy-concat nil?
|
|||
] reduce
|
||||
] if ;
|
||||
|
||||
: lcomp ( list quot -- result )
|
||||
[ lcartesian-product* ] dip lmap-lazy ;
|
||||
: lcartesian-map ( list quot: ( elt1 elt2 -- newelt ) -- result )
|
||||
[ lcartesian-product* ] dip [ first2 ] prepose lmap-lazy ;
|
||||
|
||||
: lcomp* ( list guards quot -- result )
|
||||
: 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) ] }
|
||||
[ (lmerge) ]
|
||||
} cond ;
|
||||
|
||||
TUPLE: lazy-io stream car cdr quot ;
|
||||
|
@ -308,7 +314,7 @@ M: lazy-io car
|
|||
dup car>> [
|
||||
nip
|
||||
] [
|
||||
[ ] [ stream>> ] [ quot>> ] tri
|
||||
dup [ stream>> ] [ quot>> ] bi
|
||||
call( stream -- value ) [ >>car ] [ drop nil ] if*
|
||||
] if* ;
|
||||
|
||||
|
|
|
@ -42,9 +42,9 @@ M: object nil? drop f ;
|
|||
|
||||
: cadr ( list -- elt ) cdr car ; inline
|
||||
|
||||
: 2car ( list -- car cadr ) [ car ] [ cadr ] bi ; inline
|
||||
: 2car ( list -- car cadr ) uncons car ; inline
|
||||
|
||||
: 3car ( list -- car cadr caddr ) [ car ] [ cadr ] [ cdr cadr ] tri ; inline
|
||||
: 3car ( list -- car cadr caddr ) uncons uncons car ; inline
|
||||
|
||||
: lnth ( n list -- elt ) swap [ cdr ] times car ; inline
|
||||
|
||||
|
@ -62,7 +62,9 @@ PRIVATE>
|
|||
swapd leach ; inline
|
||||
|
||||
:: foldr ( ... list identity quot: ( ... prev elt -- ... next ) -- ... result )
|
||||
list nil? [ identity ] [
|
||||
list nil? [
|
||||
identity
|
||||
] [
|
||||
list cdr identity quot foldr
|
||||
list car quot call
|
||||
] if ; inline recursive
|
||||
|
@ -80,9 +82,7 @@ PRIVATE>
|
|||
[ lreverse ] dip [ swons ] foldl ;
|
||||
|
||||
: lcut ( list index -- before after )
|
||||
[ nil ] dip
|
||||
[ [ unswons ] dip cons ] times
|
||||
lreverse swap ;
|
||||
[ nil ] dip [ [ unswons ] dip cons ] times lreverse swap ;
|
||||
|
||||
: sequence>list ( sequence -- list )
|
||||
<reversed> nil [ swons ] reduce ;
|
||||
|
|
Loading…
Reference in New Issue