lazy-lists: make seq>list more efficient

chris.double 2006-10-05 10:33:00 +00:00
parent 48a3fad1a1
commit b7dc804433
4 changed files with 116 additions and 76 deletions

View File

@ -4,7 +4,7 @@
! Updated by Matthew Willis, July 2006
! Updated by Chris Double, September 2006
!
USING: kernel sequences math vectors arrays namespaces generic ;
USING: kernel sequences math vectors arrays namespaces generic errors ;
IN: lazy-lists
TUPLE: promise quot forced? value ;
@ -22,9 +22,13 @@ C: promise ( quot -- promise ) [ set-promise-quot ] keep ;
promise-value ;
TUPLE: cons car cdr ;
GENERIC: car ( cons -- car )
GENERIC: cdr ( cons -- cdr )
GENERIC: nil? ( cons -- bool )
GENERIC: car ( cons -- car )
GENERIC: cdr ( cons -- cdr )
GENERIC: nil? ( cons -- bool )
GENERIC: list? ( object -- bool )
M: object list? ( object -- bool )
drop f ;
C: cons ( car cdr -- list )
[ set-cons-cdr ] keep
@ -42,6 +46,9 @@ M: cons cdr ( cons -- cdr )
M: cons nil? ( cons -- bool )
nil eq? ;
M: cons list? ( object -- bool )
drop t ;
: cons ( car cdr -- list )
<cons> ;
@ -68,6 +75,9 @@ M: promise cdr ( promise -- cdr )
M: promise nil? ( cons -- bool )
force nil? ;
M: promise list? ( object -- bool )
drop t ;
DEFER: lunit
DEFER: lnth
TUPLE: list ;
@ -133,6 +143,9 @@ M: memoized-cons nil? ( memoized-cons -- bool )
memoized-cons-nil?
] if ;
M: memoized-cons list? ( object -- bool )
drop t ;
TUPLE: lazy-map cons quot ;
: lmap ( list quot -- result )
@ -149,6 +162,9 @@ M: lazy-map cdr ( lazy-map -- cdr )
M: lazy-map nil? ( lazy-map -- bool )
lazy-map-cons nil? ;
M: lazy-map list? ( object -- bool )
drop t ;
TUPLE: lazy-map-with value cons quot ;
: lmap-with ( value list quot -- result )
@ -167,6 +183,9 @@ M: lazy-map-with cdr ( lazy-map-with -- cdr )
M: lazy-map-with nil? ( lazy-map-with -- bool )
lazy-map-with-cons nil? ;
M: lazy-map-with list? ( object -- bool )
drop t ;
TUPLE: lazy-take n cons ;
: ltake ( n list -- result )
@ -182,6 +201,9 @@ M: lazy-take cdr ( lazy-take -- cdr )
M: lazy-take nil? ( lazy-take -- bool )
lazy-take-n zero? ;
M: lazy-take list? ( object -- bool )
drop t ;
TUPLE: lazy-subset cons quot ;
: lsubset ( list quot -- list )
@ -221,6 +243,9 @@ M: lazy-subset nil? ( lazy-subset -- bool )
] if
] if ;
M: lazy-subset list? ( object -- bool )
drop t ;
: list>vector ( list -- vector )
[ [ , ] leach ] V{ } make ;
@ -251,6 +276,9 @@ M: lazy-append nil? ( lazy-append -- bool )
lazy-append-list2 nil?
] if ;
M: lazy-append list? ( object -- bool )
drop t ;
TUPLE: lazy-from-by n quot ;
: lfrom-by ( n quot -- list )
@ -269,6 +297,9 @@ M: lazy-from-by cdr ( lazy-from-by -- cdr )
M: lazy-from-by nil? ( lazy-from-by -- bool )
drop f ;
M: lazy-from-by list? ( object -- bool )
drop t ;
TUPLE: lazy-zip list1 list2 ;
: lzip ( list1 list2 -- lazy-zip )
@ -283,9 +314,39 @@ M: lazy-zip cdr ( lazy-zip -- cdr )
M: lazy-zip nil? ( lazy-zip -- bool )
drop f ;
: seq>list ( seq -- list )
reverse nil [ swap cons ] reduce ;
M: lazy-zip list? ( object -- bool )
drop t ;
TUPLE: sequence-cons index seq ;
: seq>list ( index seq -- list )
2dup length >= [
2drop nil
] [
<sequence-cons>
] if ;
M: sequence-cons car ( sequence-cons -- car )
[ sequence-cons-index ] keep
sequence-cons-seq nth ;
M: sequence-cons cdr ( sequence-cons -- cdr )
[ sequence-cons-index 1+ ] keep
sequence-cons-seq seq>list ;
M: sequence-cons nil? ( sequence-cons -- bool )
drop f ;
M: sequence-cons list? ( object -- bool )
drop t ;
: >list ( object -- list )
{
{ [ dup sequence? ] [ 0 swap seq>list ] }
{ [ dup list? ] [ ] }
{ [ t ] [ "Could not convert object to a list" throw ] }
} cond ;
: lconcat ( list -- result )
list>array nil [ lappend ] reduce ;

View File

@ -16,27 +16,32 @@ HELP: force
HELP: <cons>
{ $values { "car" "the head of the lazy list" } { "cdr" "the tail of the lazy list" } { "cons" "a cons object" } }
{ $description "Constructs a cons cell." }
{ $see-also cons car cdr nil nil? } ;
{ $see-also cons car cdr nil nil? list? } ;
HELP: car
{ $values { "cons" "a cons object" } { "car" "the first item in the list" } }
{ $description "Returns the first item in the list." }
{ $see-also cons cdr nil nil? } ;
{ $see-also cons cdr nil nil? list? } ;
HELP: cdr
{ $values { "cons" "a cons object" } { "cdr" "a cons object" } }
{ $description "Returns the tail of the list." }
{ $see-also cons car nil nil? } ;
{ $see-also cons car nil nil? list? } ;
HELP: nil
{ $values { "cons" "An empty cons" } }
{ $description "Returns a representation of an empty list" }
{ $see-also cons car cdr nil? } ;
{ $see-also cons car cdr nil? list? } ;
HELP: nil?
{ $values { "cons" "a cons object" } }
{ $description "Return true if the cons object is the nil cons." }
{ $see-also cons car cdr nil } ;
{ $see-also cons car cdr nil list? } ;
HELP: list?
{ $values { "object" "an object" } }
{ $description "Returns true if the object conforms to the list protocol." }
{ $see-also cons car cdr nil } ;
HELP: cons
{ $values { "car" "the head of the lazy list" } { "cdr" "the tail of the lazy list" } { "cons" "a cons object" } }
@ -46,12 +51,17 @@ HELP: cons
HELP: 1list
{ $values { "obj" "an object" } { "cons" "a cons object" } }
{ $description "Create a list with 1 element." }
{ $see-also 2list } ;
{ $see-also 2list 3list } ;
HELP: 2list
{ $values { "a" "an object" } { "b" "an object" } { "cons" "a cons object" } }
{ $description "Create a list with 2 elements." }
{ $see-also 1list } ;
{ $see-also 1list 3list } ;
HELP: 3list
{ $values { "a" "an object" } { "b" "an object" } { "c" "an object" } { "cons" "a cons object" } }
{ $description "Create a list with 3 elements." }
{ $see-also 1list 2list } ;
HELP: lazy-cons
{ $values { "car" "a quotation with stack effect ( -- X )" } { "cdr" "a quotation with stack effect ( -- cons )" } { "cons" "the resulting cons object" } }
@ -139,9 +149,14 @@ HELP: lfrom
{ $see-also leach lmap lmap-with ltake lsubset lfrom-by lconcat lcartesian-product lcartesian-product* lcomp lcomp* } ;
HELP: seq>list
{ $values { "seq" "a sequence" } { "list" "a list" } }
{ $description "Convert the sequence into a list." }
{ $see-also cons } ;
{ $values { "index" "an integer 0 or greater" } { "seq" "a sequence" } { "list" "a list" } }
{ $description "Convert the sequence into a list, starting from the 'index' offset into the sequence." }
{ $see-also >list } ;
HELP: >list
{ $values { "object" "an object" } { "list" "a list" } }
{ $description "Convert the object into a list. Existing lists are passed through intact, sequences are converted using " { $link seq>list } " and other objects cause an error to be thrown." }
{ $see-also seq>list } ;
HELP: lconcat
{ $values { "list" "a list of lists" } { "result" "a list" } }

View File

@ -9,5 +9,4 @@ PROVIDE: contrib/lazy-lists {
"examples.factor"
} {
"test/lists.factor"
"test/examples.factor"
} ;

View File

@ -1,60 +1,25 @@
! Copyright (C) 2006 Matthew Willis.
!
! Redistribution and use in source and binary forms, with or without
! modification, are permitted provided that the following conditions are met:
!
! 1. Redistributions of source code must retain the above copyright notice,
! this list of conditions and the following disclaimer.
!
! 2. Redistributions in binary form must reproduce the above copyright notice,
! this list of conditions and the following disclaimer in the documentation
! and/or other materials provided with the distribution.
!
! THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
! INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
! FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
! DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
! OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
! WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
USING: lazy-lists test kernel math io ;
! Copyright (C) 2006 Matthew Willis and Chris Double.
! See http://factorcode.org/license.txt for BSD license.
!
USING: lazy-lists test kernel math io sequences ;
IN: temporary
[ t ] [ nil nil? ] unit-test
[ 5 ] [ 5 lunit car ] unit-test
[ f ] [ nil nil cons nil? ] unit-test
[ 5 t ] [ 5 lunit uncons nil? ] unit-test
[ 6 ] [
5 6 lunit cons
1 swap lnth
] unit-test
[ 12 13 t ] [
5 6 lunit cons
[ 7 + ] lmap uncons uncons nil?
] unit-test
[ 5 6 t ] [
5 6 7 lunit cons cons 2 swap ltake
uncons uncons nil?
] unit-test
[ 6 7 t ] [ 5 6 7 lunit cons cons [ 5 > ] lsubset
uncons uncons nil? ] unit-test
[ 7 t ] [ 5 6 7 lunit cons cons [ 6 > ] lsubset
uncons nil? ] unit-test
[ 1 3 5 t ] [ { 1 3 5 } array>list
uncons uncons uncons nil? ] unit-test
[ { 1 3 5 } ] [ { 1 3 5 } array>list list>array ] unit-test
[ { 1 2 3 4 5 6 7 8 9 } ] [
{ 1 2 3 } array>list
{ 4 5 6 } array>list
{ 7 8 9 } array>list
lunit cons cons lappend* list>array ] unit-test
[ { 1 2 3 4 5 6 } ]
[ { 1 2 3 } array>list { 4 5 6 } array>list
lappend list>array ] unit-test
[ ] [ { 1 2 3 } array>list [ 3 + number>string print ] leach ] unit-test
[ { 1 2 3 4 } ]
[ 0 lfrom [ 5 < ] lsubset [ 0 > ] lsubset 4 swap ltake list>array ] unit-test
[ { 1 2 3 4 } ] [
{ 1 2 3 4 } >list list>array
] unit-test
[ { { 1 4 } { 1 5 } { 2 4 } { 2 5 } { 3 4 } { 3 5 } } ] [
{ 1 2 3 } >list { 4 5 } >list 2list lcartesian-product* list>array
] unit-test
[ { { 1 4 } { 1 5 } { 2 4 } { 2 5 } { 3 4 } { 3 5 } } ] [
{ 1 2 3 } >list { 4 5 } >list lcartesian-product list>array
] unit-test
[ { 5 6 6 7 7 8 } ] [
{ 1 2 3 } >list { 4 5 } >list 2list [ first2 + ] lcomp list>array
] unit-test
[ { 5 6 7 8 } ] [
{ 1 2 3 } >list { 4 5 } >list 2list { [ first odd? ] } [ first2 + ] lcomp* list>array
] unit-test