mnmap generalized m-to-n sequence combinator
parent
d9fa247b84
commit
d2c1f7c9c1
|
@ -89,6 +89,11 @@ HELP: ndup
|
|||
}
|
||||
} ;
|
||||
|
||||
HELP: dupn
|
||||
{ $values { "n" integer } }
|
||||
{ $description "Calls " { $link dup } " enough times that " { $snippet "n" } " references to the element at the top of the stack before " { $snippet "dupn" } " is called are on the top of the stack." }
|
||||
{ $notes { $snippet "2 dupn" } " is equivalent to " { $link dup } ". " { $snippet "1 dupn" } " is a no-op. " { $snippet "0 dupn" } " is equivalent to " { $link drop } "." } ;
|
||||
|
||||
HELP: nnip
|
||||
{ $values { "n" integer } }
|
||||
{ $description "A generalization of " { $link nip } " and " { $link 2nip }
|
||||
|
@ -149,7 +154,7 @@ HELP: -nrot
|
|||
} ;
|
||||
|
||||
HELP: ndip
|
||||
{ $values { "quot" quotation } { "n" integer } }
|
||||
{ $values { "n" integer } }
|
||||
{ $description "A generalization of " { $link dip } " that can work "
|
||||
"for any stack depth. The quotation will be called with a stack that "
|
||||
"has 'n' items removed first. The 'n' items are then put back on the "
|
||||
|
@ -236,18 +241,51 @@ HELP: nspread
|
|||
{ $description "A generalization of " { $link spread } " that can work for any quotation arity."
|
||||
} ;
|
||||
|
||||
HELP: cleave*
|
||||
{ $values { "n" integer } }
|
||||
{ $description "Like " { $link cleave } ", but instead of taking a single array of quotations, cleaves using quotations taken from the top " { $snippet "n" } " elements of the datastack." }
|
||||
{ $notes "This word can be used with " { $link apply-curry } " to generalize the " { $snippet "bi-curry@ bi" } " or " { $snippet "tri-curry@ tri" } " dataflow patterns." } ;
|
||||
|
||||
HELP: spread*
|
||||
{ $values { "n" integer } }
|
||||
{ $description "Like " { $link spread } ", but instead of taking a single array of quotations, spreads using quotations taken from the top " { $snippet "n" } " elements of the datastack." }
|
||||
{ $notes "This word can be used with " { $link apply-curry } " to generalize the " { $snippet "bi-curry@ bi*" } " or " { $snippet "tri-curry@ tri*" } " dataflow patterns." } ;
|
||||
|
||||
HELP: apply-curry
|
||||
{ $values { "...a" { $snippet "n" } " values on the datastack" } { "quot" quotation } { "n" integer } }
|
||||
{ $description "Curries each of the top " { $snippet "n" } " items of the datastack onto " { $snippet "quot" } ", leaving " { $snippet "n" } " quotations on the datastack. A generalization of " { $link bi-curry@ } " and " { $link tri-curry@ } "." }
|
||||
{ $notes "This word can be used with " { $link cleave* } " and " { $link spread* } " to generalize dataflow patterns such as " { $snippet "bi-curry@ bi" } ", " { $snippet "tri-curry@ tri" } ", " { $snippet "bi-curry@ bi*" } ", and " { $snippet "tri-curry@ tri*" } "." } ;
|
||||
|
||||
HELP: cleave-curry
|
||||
{ $values { "a" object } { "...quot" { $snippet "n" } " quotations on the datastack" } { "n" integer } }
|
||||
{ $description "Curries " { $snippet "a" } " onto the " { $snippet "n" } " quotations on the top of the datastack. A generalization of " { $link bi-curry } " and " { $link tri-curry } "." }
|
||||
{ $notes "This word can be used with " { $link cleave* } " and " { $link spread* } " to generalize dataflow patterns such as " { $snippet "bi-curry bi" } ", " { $snippet "tri-curry tri" } ", " { $snippet "bi-curry bi*" } ", and " { $snippet "tri-curry tri*" } "." } ;
|
||||
|
||||
HELP: spread-curry
|
||||
{ $values { "...a" { $snippet "n" } " objects on the datastack" } { "...quot" { $snippet "n" } " quotations on the datastack" } { "n" integer } }
|
||||
{ $description "Curries the " { $snippet "n" } " quotations on the top of the datastack with the " { $snippet "n" } " values just below them. A generalization of " { $link bi-curry* } " and " { $link tri-curry* } "." }
|
||||
{ $notes "This word can be used with " { $link cleave* } " and " { $link spread* } " to generalize dataflow patterns such as " { $snippet "bi-curry* bi" } ", " { $snippet "tri-curry* tri" } ", " { $snippet "bi-curry* bi*" } ", and " { $snippet "tri-curry* tri*" } "." } ;
|
||||
|
||||
HELP: neach
|
||||
{ $values { "...seq" "a set of " { $snippet "n" } " sequences" } { "quot" "a quotation with stack effect " { $snippet "( ...element -- )" } } { "n" integer } }
|
||||
{ $values { "...seq" { $snippet "n" } " sequences on the datastack" } { "quot" "a quotation with stack effect " { $snippet "( ...element -- )" } } { "n" integer } }
|
||||
{ $description "A generalization of " { $link each } ", " { $link 2each } ", and " { $link 3each } " that can iterate over any number of sequences in parallel." } ;
|
||||
|
||||
HELP: nmap
|
||||
{ $values { "...seq" "a set of " { $snippet "n" } " sequences" } { "quot" "a quotation with stack effect " { $snippet "( ...element -- result )" } } { "n" integer } { "result" "a sequence of the same type as the first " { $snippet "seq" } } }
|
||||
{ $values { "...seq" { $snippet "n" } " sequences on the datastack" } { "quot" "a quotation with stack effect " { $snippet "( ...element -- result )" } } { "n" integer } { "result" "a sequence of the same type as the first " { $snippet "seq" } } }
|
||||
{ $description "A generalization of " { $link map } ", " { $link 2map } ", and " { $link 3map } " that can map over any number of sequences in parallel." } ;
|
||||
|
||||
HELP: nmap-as
|
||||
{ $values { "...seq" "a set of " { $snippet "n" } " sequences" } { "quot" "a quotation with stack effect " { $snippet "( ...element -- result )" } } { "exemplar" sequence } { "n" integer } { "result" "a sequence of the same type as " { $snippet "exemplar" } } }
|
||||
{ $values { "...seq" { $snippet "n" } " sequences on the datastack" } { "quot" "a quotation with stack effect " { $snippet "( ...element -- result )" } } { "exemplar" sequence } { "n" integer } { "result" "a sequence of the same type as " { $snippet "exemplar" } } }
|
||||
{ $description "A generalization of " { $link map-as } ", " { $link 2map-as } ", and " { $link 3map-as } " that can map over any number of sequences in parallel." } ;
|
||||
|
||||
HELP: mnmap
|
||||
{ $values { "m*seq" { $snippet "m" } " sequences on the datastack" } { "quot" "a quotation with stack effect " { $snippet "( m*element -- result*n )" } } { "m" integer } { "n" integer } { "result*n" { $snippet "n" } " sequences of the same type as the first " { $snippet "seq" } } }
|
||||
{ $description "A generalization of " { $link map } ", " { $link 2map } ", and " { $link 3map } " that can map over any number of sequences in parallel and provide any number of output sequences." } ;
|
||||
|
||||
HELP: mnmap-as
|
||||
{ $values { "m*seq" { $snippet "m" } " sequences on the datastack" } { "quot" "a quotation with stack effect " { $snippet "( m*element -- result*n )" } } { "n*exemplar" { $snippet "n" } " sequences on the datastack" } { "m" integer } { "n" integer } { "result*n" { $snippet "n" } " sequences of the same type as the " { $snippet "exemplar" } "s" } }
|
||||
{ $description "A generalization of " { $link map-as } ", " { $link 2map-as } ", and " { $link 3map-as } " that can map over any number of sequences in parallel and provide any number of output sequences of distinct types." } ;
|
||||
|
||||
HELP: mnswap
|
||||
{ $values { "m" integer } { "n" integer } }
|
||||
{ $description "Swaps the top " { $snippet "m" } " stack elements with the " { $snippet "n" } " elements directly underneath." }
|
||||
|
@ -339,6 +377,7 @@ ARTICLE: "sequence-generalizations" "Generalized sequence operations"
|
|||
ARTICLE: "shuffle-generalizations" "Generalized shuffle words"
|
||||
{ $subsections
|
||||
ndup
|
||||
dupn
|
||||
npick
|
||||
nrot
|
||||
-nrot
|
||||
|
@ -357,9 +396,16 @@ ARTICLE: "combinator-generalizations" "Generalized combinators"
|
|||
napply
|
||||
ncleave
|
||||
nspread
|
||||
cleave*
|
||||
spread*
|
||||
apply-curry
|
||||
cleave-curry
|
||||
spread-curry
|
||||
neach
|
||||
nmap
|
||||
nmap-as
|
||||
mnmap
|
||||
mnmap-as
|
||||
} ;
|
||||
|
||||
ARTICLE: "other-generalizations" "Additional generalizations"
|
||||
|
|
|
@ -86,6 +86,16 @@ IN: generalizations.tests
|
|||
[ 4 nappend ] 4 nmap ;
|
||||
: nmap-as-test ( a b c d -- e )
|
||||
[ 4 nappend ] [ ] 4 nmap-as ;
|
||||
: mnmap-3-test ( a b c d -- e f g )
|
||||
[ append ] 4 3 mnmap ;
|
||||
: mnmap-2-test ( a b c d -- e f )
|
||||
[ [ append ] 2bi@ ] 4 2 mnmap ;
|
||||
: mnmap-as-test ( a b c d -- e f )
|
||||
[ [ append ] 2bi@ ] { } [ ] 4 2 mnmap-as ;
|
||||
: mnmap-1-test ( a b c d -- e )
|
||||
[ 4 nappend ] 4 1 mnmap ;
|
||||
: mnmap-0-test ( a b c d -- )
|
||||
[ 4 nappend print ] 4 0 mnmap ;
|
||||
|
||||
[ """A1a!
|
||||
B2b@
|
||||
|
@ -116,3 +126,87 @@ D4d$
|
|||
{ "!" "@" "#" "$" }
|
||||
nmap-as-test
|
||||
] unit-test
|
||||
|
||||
[
|
||||
{ "A" "B" "C" "D" }
|
||||
{ "1" "2" "3" "4" }
|
||||
{ "a!" "b@" "c#" "d$" }
|
||||
] [
|
||||
{ "A" "B" "C" "D" }
|
||||
{ "1" "2" "3" "4" }
|
||||
{ "a" "b" "c" "d" }
|
||||
{ "!" "@" "#" "$" }
|
||||
mnmap-3-test
|
||||
] unit-test
|
||||
|
||||
[
|
||||
{ "A1" "B2" "C3" "D4" }
|
||||
{ "a!" "b@" "c#" "d$" }
|
||||
] [
|
||||
{ "A" "B" "C" "D" }
|
||||
{ "1" "2" "3" "4" }
|
||||
{ "a" "b" "c" "d" }
|
||||
{ "!" "@" "#" "$" }
|
||||
mnmap-2-test
|
||||
] unit-test
|
||||
|
||||
[
|
||||
{ "A1" "B2" "C3" "D4" }
|
||||
[ "a!" "b@" "c#" "d$" ]
|
||||
] [
|
||||
{ "A" "B" "C" "D" }
|
||||
{ "1" "2" "3" "4" }
|
||||
{ "a" "b" "c" "d" }
|
||||
{ "!" "@" "#" "$" }
|
||||
mnmap-as-test
|
||||
] unit-test
|
||||
|
||||
[ { "A1a!" "B2b@" "C3c#" "D4d$" } ]
|
||||
[
|
||||
{ "A" "B" "C" "D" }
|
||||
{ "1" "2" "3" "4" }
|
||||
{ "a" "b" "c" "d" }
|
||||
{ "!" "@" "#" "$" }
|
||||
mnmap-1-test
|
||||
] unit-test
|
||||
|
||||
[ """A1a!
|
||||
B2b@
|
||||
C3c#
|
||||
D4d$
|
||||
""" ] [
|
||||
{ "A" "B" "C" "D" }
|
||||
{ "1" "2" "3" "4" }
|
||||
{ "a" "b" "c" "d" }
|
||||
{ "!" "@" "#" "$" }
|
||||
[ mnmap-0-test ] with-string-writer
|
||||
] unit-test
|
||||
|
||||
[ 6 8 10 12 ] [
|
||||
1 2 3 4
|
||||
5 6 7 8 [ + ] 4 apply-curry 4 spread*
|
||||
] unit-test
|
||||
|
||||
[ 6 ] [ 5 [ 1 + ] 1 spread* ] unit-test
|
||||
[ 6 ] [ 5 [ 1 + ] 1 cleave* ] unit-test
|
||||
[ 6 ] [ 5 [ 1 + ] 1 napply ] unit-test
|
||||
|
||||
[ 6 ] [ 6 0 spread* ] unit-test
|
||||
[ 6 ] [ 6 0 cleave* ] unit-test
|
||||
[ 6 ] [ 6 [ 1 + ] 0 napply ] unit-test
|
||||
|
||||
[ 6 7 8 9 ] [
|
||||
1
|
||||
5 6 7 8 [ + ] 4 apply-curry 4 cleave*
|
||||
] unit-test
|
||||
|
||||
[ 8 3 8 3/2 ] [
|
||||
6 5 4 3
|
||||
2 [ + ] [ - ] [ * ] [ / ] 4 cleave-curry 4 spread*
|
||||
] unit-test
|
||||
|
||||
[ 8 4 0 -3 ] [
|
||||
6 5 4 3
|
||||
2 1 0 -1 [ + ] [ - ] [ * ] [ / ] 4 spread-curry 4 spread*
|
||||
] unit-test
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
! Copyright (C) 2007, 2009 Chris Double, Doug Coleman, Eduardo
|
||||
! Cavazos, Slava Pestov.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: kernel sequences sequences.private math combinators
|
||||
macros math.order quotations fry effects memoize.private ;
|
||||
USING: kernel kernel.private sequences sequences.private math
|
||||
combinators macros math.order math.ranges quotations fry effects
|
||||
memoize.private ;
|
||||
IN: generalizations
|
||||
|
||||
<<
|
||||
|
@ -42,6 +43,10 @@ MACRO: nover ( n -- )
|
|||
MACRO: ndup ( n -- )
|
||||
dup '[ _ npick ] n*quot ;
|
||||
|
||||
MACRO: dupn ( n -- )
|
||||
[ [ drop ] ]
|
||||
[ 1 - [ dup ] n*quot ] if-zero ;
|
||||
|
||||
MACRO: nrot ( n -- )
|
||||
1 - [ ] [ '[ _ dip swap ] ] repeat ;
|
||||
|
||||
|
@ -69,8 +74,8 @@ MACRO: nnip ( n -- )
|
|||
MACRO: ntuck ( n -- )
|
||||
2 + '[ dup _ -nrot ] ;
|
||||
|
||||
MACRO: ndip ( quot n -- )
|
||||
[ '[ _ dip ] ] times ;
|
||||
MACRO: ndip ( n -- )
|
||||
[ [ dip ] curry ] n*quot [ call ] compose ;
|
||||
|
||||
MACRO: nkeep ( quot n -- )
|
||||
tuck '[ _ ndup _ _ ndip ] ;
|
||||
|
@ -96,9 +101,29 @@ MACRO: nspread ( quots n -- )
|
|||
'[ [ _ _ nspread ] _ ndip @ ]
|
||||
] if ;
|
||||
|
||||
MACRO: spread* ( n -- )
|
||||
[ [ ] ] [
|
||||
1 swap [a,b) [ '[ [ [ _ ndip ] curry ] dip compose ] ] map [ ] concat-as
|
||||
[ call ] compose
|
||||
] if-zero ;
|
||||
|
||||
MACRO: cleave* ( n -- )
|
||||
[ [ ] ]
|
||||
[ 1 - [ [ [ keep ] curry ] dip compose ] n*quot [ call ] compose ]
|
||||
if-zero ;
|
||||
|
||||
MACRO: napply ( n -- )
|
||||
[ [ drop ] ] dip [ '[ tuck _ 2dip call ] ] times ;
|
||||
|
||||
: apply-curry ( ...a quot n -- )
|
||||
[ [curry] ] dip napply ; inline
|
||||
|
||||
: cleave-curry ( a ...quot n -- )
|
||||
[ [curry] ] swap [ napply ] [ cleave* ] bi ; inline
|
||||
|
||||
: spread-curry ( ...a ...quot n -- )
|
||||
[ [curry] ] swap [ napply ] [ spread* ] bi ; inline
|
||||
|
||||
MACRO: mnswap ( m n -- )
|
||||
1 + '[ _ -nrot ] swap '[ _ _ napply ] ;
|
||||
|
||||
|
@ -121,12 +146,16 @@ MACRO: nmin-length ( n -- )
|
|||
dup 1 - [ min ] n*quot
|
||||
'[ [ length ] _ napply @ ] ;
|
||||
|
||||
MACRO: nnth-unsafe ( n -- )
|
||||
'[ [ '[ _ nth-unsafe ] keep ] _ napply drop ] ;
|
||||
: nnth-unsafe ( n ...seq n -- )
|
||||
[ nth-unsafe ] swap [ apply-curry ] [ cleave* ] bi ; inline
|
||||
MACRO: nset-nth-unsafe ( n -- )
|
||||
[ [ drop ] ]
|
||||
[ '[ [ set-nth-unsafe ] _ [ apply-curry ] [ cleave-curry ] [ spread* ] tri ] ]
|
||||
if-zero ;
|
||||
|
||||
MACRO: (neach) ( n -- )
|
||||
: (neach) ( ...seq quot n -- len quot' )
|
||||
dup dup dup
|
||||
'[ [ [ _ nmin-length ] _ nkeep [ _ nnth-unsafe ] _ ncurry ] dip compose ] ;
|
||||
'[ [ _ nmin-length ] _ nkeep [ _ nnth-unsafe ] _ ncurry ] dip compose ; inline
|
||||
|
||||
: neach ( ...seq quot n -- )
|
||||
(neach) each-integer ; inline
|
||||
|
@ -136,3 +165,34 @@ MACRO: (neach) ( n -- )
|
|||
|
||||
: nmap ( ...seq quot n -- result )
|
||||
dup '[ [ _ npick ] dip swap ] dip nmap-as ; inline
|
||||
|
||||
MACRO: nnew-sequence ( n -- )
|
||||
[ [ drop ] ]
|
||||
[ dup '[ [ new-sequence ] _ apply-curry _ cleave* ] ] if-zero ;
|
||||
|
||||
: nnew-like ( len ...exemplar quot n -- result... )
|
||||
dup dup dup dup '[
|
||||
_ nover
|
||||
[ [ _ nnew-sequence ] dip call ]
|
||||
_ ndip [ like ]
|
||||
_ apply-curry
|
||||
_ spread*
|
||||
] call ; inline
|
||||
|
||||
MACRO: (ncollect) ( n -- )
|
||||
dup dup 1 +
|
||||
'[ [ [ keep ] _ ndip _ nset-nth-unsafe ] _ ncurry ] ;
|
||||
|
||||
: ncollect ( len quot ...into n -- )
|
||||
(ncollect) each-integer ; inline
|
||||
|
||||
: nmap-integers ( len quot ...exemplar n -- result... )
|
||||
dup dup dup
|
||||
'[ [ over ] _ ndip [ [ _ ncollect ] _ nkeep ] _ nnew-like ] call ; inline
|
||||
|
||||
: mnmap-as ( m*seq quot n*exemplar m n -- result*n )
|
||||
dup '[ [ _ (neach) ] _ ndip _ nmap-integers ] call ; inline
|
||||
|
||||
: mnmap ( m*seq quot m n -- result*n )
|
||||
2dup '[ [ _ npick ] dip swap _ dupn ] 2dip mnmap-as ; inline
|
||||
|
||||
|
|
Loading…
Reference in New Issue