]> gitweb.factorcode.org Git - factor.git/blob - extra/combinators/extras/extras.factor
804e89d865dda5cb4336ac24f0a8da7d68881903
[factor.git] / extra / combinators / extras / extras.factor
1 ! Copyright (C) 2013 Doug Coleman, John Benediktsson.
2 ! See https://factorcode.org/license.txt for BSD license.
3 USING: arrays assocs combinators combinators.smart
4 generalizations graphs.private kernel math math.order namespaces
5 quotations sequences sequences.generalizations sequences.private
6 sets shuffle stack-checker.transforms system words ;
7 IN: combinators.extras
8
9 : callk ( ..a quot: ( ..a -- ..b ) -- ..b quot )
10     dup [ call ] dip ; inline
11
12 : once ( quot -- ) call ; inline
13 : twice ( quot -- ) callk call ; inline
14 : thrice ( quot -- ) callk callk call ; inline
15 : forever ( quot -- ) [ t ] compose loop ; inline
16
17 MACRO: cond-case ( assoc -- quot )
18     [
19         dup callable? not [
20             [ first [ dup ] prepose ]
21             [ second [ drop ] prepose ] bi 2array
22         ] when
23     ] map [ cond ] curry ;
24
25 MACRO: cleave-array ( quots -- quot )
26     [ '[ _ cleave ] ] [ length '[ _ narray ] ] bi compose ;
27
28 : 4bi ( w x y z  p q -- )
29     [ 4keep ] dip call ; inline
30
31 : 4tri ( w x y z  p q r -- )
32     [ [ 4keep ] dip 4keep ] dip call ; inline
33
34 : quad ( x  p q r s -- )
35     [ [ [ keep ] dip keep ] dip keep ] dip call ; inline
36
37 : 2quad ( x y  p q r s -- )
38     [ [ [ 2keep ] dip 2keep ] dip 2keep ] dip call ; inline
39
40 : 3quad ( x y z  p q r s -- )
41     [ [ [ 3keep ] dip 3keep ] dip 3keep ] dip call ; inline
42
43 : 4quad ( w x y z  p q r s -- )
44     [ [ [ 4keep ] dip 4keep ] dip 4keep ] dip call ; inline
45
46 : 3bi* ( u v w  x y z  p q -- )
47     [ 3dip ] dip call ; inline
48
49 : 4bi* ( s t u v  w x y z  p q -- )
50     [ 4dip ] dip call ; inline
51
52 : 3tri* ( r s t  u v w  x y z  p q r -- )
53     [ 6 ndip ] 2dip [ 4dip ] dip call ; inline
54
55 : 4tri* ( o p q r  s t u v  w x y z  p q r -- )
56     [ 8 ndip ] 2dip [ 4dip ] dip call ; inline
57
58 : quad* ( w  x  y  z  p q r s -- )
59     [ [ [ 3dip ] dip 2dip ] dip dip ] dip call ; inline
60
61 : 2quad* ( s t  u v  w x  y z  p q r s -- )
62     [ [ [ 6 ndip ] dip 4dip ] dip 2dip ] dip call ; inline
63
64 : 3quad* ( o p q  r s t  u v w  x y z  p q r s -- )
65     [ [ [ 9 ndip ] dip 6 ndip ] dip 3dip ] dip call ; inline
66
67 : 4quad* ( k l m n  o p q r  s t u v  w x y z  p q r s -- )
68     [ [ [ 12 ndip ] dip 8 ndip ] dip 4dip ] dip call ; inline
69
70 : 3bi@ ( u v w  x y z  quot -- ) dup 3bi* ; inline
71
72 : 4bi@ ( s t u v  w x y z  quot -- ) dup 4bi* ; inline
73
74 : 3tri@ ( r s t  u v w  x y z  p q r -- )
75     dup dup 3tri* ; inline
76
77 : 4tri@ ( o p q r  s t u v  w x y z  quot -- )
78     dup dup 4tri* ; inline
79
80 : quad@ ( w  x  y  z  quot -- )
81     dup dup dup quad* ; inline
82
83 : 2quad@ ( s t  u v  w x  y z  p q r s -- )
84     dup dup dup 2quad* ; inline
85
86 : 3quad@ ( o p q  r s t  u v w  x y z  p q r s -- )
87     dup dup dup 3quad* ; inline
88
89 : 4quad@ ( k l m n  o p q r  s t u v  w x y z  p q r s -- )
90     dup dup dup 4quad* ; inline
91
92 MACRO: smart-plox ( true -- quot )
93     [ inputs [ 1 - [ and ] n*quot ] keep ] keep swap
94     '[ _ _ [ _ ndrop f ] smart-if ] ;
95
96 : throttle ( quot millis -- quot' )
97     1,000,000 * '[
98         _ nano-count { 0 } 2dup first-unsafe _ + >=
99         [ 0 swap set-nth-unsafe call ] [ 3drop ] if
100     ] ; inline
101
102 : swap-when ( x y quot: ( x -- n ) quot: ( n n -- ? ) -- x' y' )
103     '[ _ _ 2dup _ bi@ @ [ swap ] when ] call ; inline
104
105
106 ! ?1arg-result-falsify
107
108 : 1falsify ( obj/f -- obj/f ) ; inline
109 : 2falsify ( obj1 obj2 -- obj1/f obj2/f ) 2dup and [ 2drop f f ] unless ; inline
110 : 3falsify ( obj1 obj2 obj3 -- obj1/f obj2/f obj3/f ) 3dup and and [ 3drop f f f ] unless ; inline
111
112 MACRO: n-and ( n -- quot )
113     1 [-] [ and ] n*quot ;
114
115 MACRO: n*obj ( n obj -- quot )
116     1quotation n*quot ;
117
118 MACRO:: n-falsify ( n -- quot )
119     [ n ndup n n-and [ n ndrop n f n*obj ] unless ] ;
120
121 ! when both args are true, call quot. otherwise dont
122 : ?2res ( ..a obj1 obj2 quot: ( obj1 obj2 -- ? ) -- ..b )
123     [ 2dup and ] dip [ 2drop f ] if ; inline
124
125 ! try the quot, keep the original arg if quot is true
126 : ?1arg ( obj quot: ( obj -- ? ) -- obj/f )
127     [ ?call ] keepd '[ _ ] [ f ] if ; inline
128
129 : ?2arg ( obj1 obj2 quot: ( obj1 obj2 -- ? ) -- obj1/f obj2/f )
130     [ ?2res ] 2keepd '[ _ _ ] [ f f ] if ; inline
131
132 <<
133 : alist>quot* ( default assoc -- quot )
134     [ rot \ if* 3array [ ] append-as ] assoc-each ;
135
136 : cond*>quot ( assoc -- quot )
137     [ dup pair? [ [ drop ] prepend [ t ] swap 2array ] unless ] map
138     reverse! [ no-cond ] swap alist>quot* ;
139
140 DEFER: cond*
141 \ cond* [ cond*>quot ] 1 define-transform
142 \ cond* t "no-compile" set-word-prop
143 >>
144 : cond* ( assoc -- )
145     [ dup callable? [ drop t ] [ first call ] if ] map-find
146     [ dup callable? [ nip call ] [ second call ] if ]
147     [ no-cond ] if* ;
148
149 MACRO: chain ( quots -- quot )
150     <reversed> [ ] [ swap '[ [ @ @ ] [ f ] if* ] ] reduce ;
151
152 : with-output-variable ( value variable quot -- value )
153     over [ get ] curry compose with-variable ; inline
154
155 : loop1 ( ..a quot: ( ..a -- ..a obj ? ) -- ..a obj )
156     [ call ] keep '[ drop _ loop1 ] when ; inline recursive
157
158
159 : keep-1up ( quot -- quot ) keep 1 2 0 nrotated ; inline
160 : keep-2up ( quot -- quot ) keep 2 3 0 nrotated ; inline
161 : keep-3up ( quot -- quot ) keep 3 4 0 nrotated ; inline
162
163 : 2keep-1up ( quot -- quot ) 2keep 1 3 0 nrotated ; inline
164 : 2keep-2up ( quot -- quot ) 2keep 2 4 0 nrotated ; inline
165 : 2keep-3up ( quot -- quot ) 2keep 3 5 0 nrotated ; inline
166
167 : 3keep-1up ( quot -- quot ) 3keep 1 4 0 nrotated ; inline
168 : 3keep-2up ( quot -- quot ) 3keep 2 5 0 nrotated ; inline
169 : 3keep-3up ( quot -- quot ) 3keep 3 6 0 nrotated ; inline
170
171 ! d is dummy, o is object to save notation space
172 : dip-1up  ( ..a d quot: ( ..a -- ..b o d ) -- ..b d o )
173     dip swap ; inline
174 : dip-2up  ( ..a d quot: ( ..a -- ..b o1 o2 d ) -- ..b d o1 o2 )
175     dip rot rot ; inline
176
177 : 2dip-1up ( ..a d1 d2 quot: ( ..a -- ..b o d1 d2 ) -- ..b d1 d2 o )
178     2dip rot ; inline
179 : 2dip-2up ( ..a d1 d2 quot: ( ..a -- ..b o1 o2 d1 d2 ) -- ..b d1 d2 o1 o2 )
180     2dip roll roll ; inline
181
182 : 3dip-1up ( ..a d1 d2 d3 quot: ( ..a -- ..b o d1 d2 d3 ) -- ..b d1 d2 d3 o )
183     3dip roll ; inline
184 : 3dip-2up ( ..a d1 d2 d3 quot: ( ..a -- ..b o1 o2 d1 d2 d3 ) -- ..b d1 d2 d3 o1 o2 )
185     3dip 2 5 0 nrotated ; inline
186 : 3dip-3up ( ..a d1 d2 d3 quot: ( ..a -- ..b o1 o2 o3 d1 d2 d3 ) -- ..b d1 d2 d3 o1 o2 o3 )
187     3dip 3 6 0 nrotated ; inline
188
189
190 : 2craft-1up ( ..a quot1: ( ..a -- ..b o1 ) quot2: ( ..b -- ..c o2 ) -- ..c o1 o2 )
191     [ call ] dip [ dip-1up ] call ; inline
192
193 : 3craft-1up ( ..a quot1: ( ..a -- ..b o1 ) quot2: ( ..b -- ..c o2 ) quot3: ( ..c -- ..d o3 ) -- ..d o1 o2 o3 )
194     [ call ] 2dip [ dip-1up ] dip [ 2dip-1up ] call ; inline
195
196 : 4craft-1up ( ..a quot1: ( ..a -- ..b o1 ) quot2: ( ..b -- ..c o2 ) quot3: ( ..c -- ..d o3 ) quot4: ( ..d -- ..e o4 ) -- ..e o1 o2 o3 o4 )
197     [ call ] 3dip [ dip-1up ] 2dip [ 2dip-1up ] dip [ 3dip-1up ] call ; inline
198
199 : 3and ( a b c -- ? ) and and ; inline
200 : 4and ( a b c d -- ? ) and and and ; inline
201
202 : 3or ( a b c -- ? ) or or ; inline
203 : 4or ( a b c d -- ? ) or or or ; inline
204
205 ! The kept values are on the bottom of the stack
206 MACRO: keep-under ( quot -- quot' )
207     dup outputs 1 + '[ _ keep 1 _ 0 -nrotated ] ;
208
209 MACRO: 2keep-under ( quot -- quot' )
210     dup outputs 2 + '[ _ 2keep 2 _ 0 -nrotated ] ;
211
212 MACRO: 3keep-under ( quot -- quot' )
213     dup outputs 3 + '[ _ 3keep 3 _ 0 -nrotated ] ;
214
215 MACRO: 4keep-under ( quot -- quot' )
216     dup outputs 4 + '[ _ 4keep 4 _ 0 -nrotated ] ;
217
218 ! for use with assoc-map etc
219 : 1temp1d ( quot: ( a b c -- d e f ) -- quot ) '[ swap @ swap ] ; inline
220 : 1temp2d ( quot: ( a b c -- d e f ) -- quot ) '[ rot @ -rot ] ; inline
221 : 2temp2d ( quot: ( a b c d -- e f g h ) -- quot ) '[ 2 4 0 nrotated @ 2 4 0 -nrotated ] ; inline
222
223 : (closure-limit) ( vertex set quot: ( vertex -- edges ) i n -- )
224     2dup < [
225         [ 1 + ] dip
226         2reach ?adjoin [
227             [ [ dip ] keep ] 2dip [ (closure-limit) ] 2curry 2curry each
228         ] [ 5drop ] if
229     ] [
230         5drop
231     ] if ; inline recursive
232
233 : closure-limit-as ( vertex quot: ( vertex -- edges ) n exemplar -- set )
234     [ 0 ] 2dip
235     new-empty-set-like [ -roll (closure-limit) ] keep ; inline
236
237 : closure-limit ( vertex quot: ( vertex -- edges ) n -- set )
238     HS{ } closure-limit-as ; inline
239
240 : 1check ( obj quot -- obj ? ) over [ call ] dip swap ; inline
241 : 2check ( obj1 obj2 quot -- obj ? ) 2over [ call ] 2dip rot ; inline
242
243 : 1check-when ( ..a obj cond: ( ..a obj -- obj/f ) true: ( ..a obj cond -- ..b ) -- ..b )
244     [ 1check ] dip when ; inline
245 : 2check-when ( ..a obj1 obj2 cond: ( ..a obj1 obj2 -- obj/f ) true: ( ..a obj1 obj2 cond -- ..b ) -- ..b )
246     [ 2check ] dip when ; inline