]> gitweb.factorcode.org Git - factor.git/blob - basis/lists/lists.factor
Merge branch 'master' into no-elements
[factor.git] / basis / lists / lists.factor
1 ! Copyright (C) 2008 James Cash
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: kernel sequences accessors math arrays vectors classes words
4 combinators.short-circuit combinators locals ;
5 IN: lists
6
7 ! List Protocol
8 MIXIN: list
9 GENERIC: car ( cons -- car )
10 GENERIC: cdr ( cons -- cdr )
11 GENERIC: nil? ( object -- ?   )
12     
13 TUPLE: cons { car read-only } { cdr read-only } ;
14
15 C: cons cons
16
17 M: cons car ( cons -- car )
18     car>> ;
19
20 M: cons cdr ( cons -- cdr )
21     cdr>> ;
22
23 SINGLETON: +nil+
24 M: +nil+ nil? drop t ;
25 M: object nil? drop f ;
26
27 : atom? ( obj -- ? )
28     list? not ;
29
30 : nil ( -- symbol ) +nil+ ; 
31
32 : uncons ( cons -- car cdr )
33     [ car ] [ cdr ] bi ;
34
35 : swons ( cdr car -- cons )
36     swap cons ;
37
38 : unswons ( cons -- cdr car )
39     uncons swap ;
40
41 : 1list ( obj -- cons )
42     nil cons ;
43
44 : 1list? ( list -- ? )
45     { [ nil? not ] [ cdr nil? ] } 1&& ;
46
47 : 2list ( a b -- cons )
48     nil cons cons ;
49
50 : 3list ( a b c -- cons )
51     nil cons cons cons ;
52
53 : cadr ( list -- elt )    
54     cdr car ;
55  
56 : 2car ( list -- car caar )    
57     [ car ] [ cdr car ] bi ;
58  
59 : 3car ( list -- car cadr caddr )    
60     [ car ] [ cdr car ] [ cdr cdr car ] tri ;
61
62 : lnth ( n list -- elt )
63     swap [ cdr ] times car ;
64
65 <PRIVATE
66 : (leach) ( list quot -- cdr quot )
67     [ [ car ] dip call ] [ [ cdr ] dip ] 2bi ; inline
68 PRIVATE>
69
70 : leach ( list quot: ( elt -- ) -- )
71     over nil? [ 2drop ] [ (leach) leach ] if ; inline recursive
72
73 : lmap ( list quot: ( elt -- ) -- result )
74     over nil? [ drop ] [ (leach) lmap cons ] if ; inline recursive
75
76 : foldl ( list identity quot: ( obj1 obj2 -- obj ) -- result )
77     swapd leach ; inline
78
79 :: foldr ( list identity quot: ( obj1 obj2 -- obj ) -- result )
80     list nil? [ identity ] [
81         list cdr identity quot foldr
82         list car quot call
83     ] if ; inline recursive
84
85 : llength ( list -- n )
86     0 [ drop 1+ ] foldl ;
87
88 : lreverse ( list -- newlist )    
89     nil [ swap cons ] foldl ;
90
91 : lappend ( list1 list2 -- newlist )    
92     [ lreverse ] dip [ swap cons ] foldl ;
93
94 : lcut ( list index -- before after )
95     [ nil ] dip
96     [ [ [ cdr ] [ car ] bi ] dip cons ] times
97     lreverse swap ;
98
99 : sequence>cons ( sequence -- list )    
100     <reversed> nil [ swap cons ] reduce ;
101
102 <PRIVATE
103 : same? ( obj1 obj2 -- ? ) 
104     [ class ] bi@ = ;
105 PRIVATE>
106
107 : deep-sequence>cons ( sequence -- cons )
108     [ <reversed> ] keep nil
109     [ tuck same? [ deep-sequence>cons ] when swons ] with reduce ;
110
111 <PRIVATE
112 :: (lmap>vector) ( acc list quot: ( elt -- elt' ) -- acc )
113     list nil? [ acc ] [
114         list car quot call acc push
115         acc list cdr quot (lmap>vector)
116     ] if ; inline recursive
117
118 : lmap>vector ( list quot -- array )
119     [ V{ } clone ] 2dip (lmap>vector) ; inline
120 PRIVATE>
121
122 : lmap-as ( list quot exemplar -- sequence )
123     [ lmap>vector ] dip like ; inline
124
125 : lmap>array ( list quot -- array )
126     { } lmap-as ; inline
127
128 : deep-list>array ( list -- array )    
129     [
130         {
131             { [ dup nil? ] [ drop { } ] }
132             { [ dup list? ] [ deep-list>array ] }
133             [ ]
134         } cond
135     ] lmap>array ;
136
137 : list>array ( list -- array )    
138     [ ] lmap>array ;
139
140 :: traverse ( list pred quot: ( list/elt -- result ) -- result )
141     list [| elt |
142         elt dup pred call [ quot call ] when
143         dup list? [ pred quot traverse ] when
144     ] lmap ; inline recursive
145
146 INSTANCE: cons list
147 INSTANCE: +nil+ list