[stack] improved parallel combinator
John Nowak <[email protected]>
| Newsgroups | gmane.comp.lang.concatenative |
|---|---|
| Message-ID | <[email protected]> |
I actually really like this one. No more weird pseudo-vector stuff.
Here are the semantics:
S (| F |) == S F
S (| F , G |) == S F { S G } peek
S (| F , G , H |) == S F { S G } peek { S H } peek
..
Here are some examples:
5 (| sq , neg |) == 25 -5
4 3 (| + , * |) == 7 12
1 2 (| nip , drop |) == 2 1 ! same as 'swap'
{ 2 3 4 } (| rest , first |) == { 3 4 } 2 ! same as 'unclip'
Here is the implementation:
: infra-seq ( seq seq -- seq )
[ [ with-datastack peek ] curry keep ] each drop ;
: datastack-tail ( x -- x seq )
[ datastack ] dip swap ;
: parallel ( seq -- )
datastack-tail [ unclip dip ] dip swap infra-seq ;
! "banana syntax" for 'parallel':
! (| F , G |) == { [ F ] [ G ] } parallel
: |) ;
: (| \ |)
[ \ , 1array split [ >quotation ] map ] parse-literal
\ parallel suffix ; parsing
For those not familiar with Factor:
{ x0 .. xN } peek == xN
{ x S } unclip == { S } x
[ F ] x slip == F x
{ S } [ F ] with-datastack == { S F }
The trick was realizing that the first quotation should be applied
directly to the main stack. Lacking this, you'd need to explicitly
indicate how many values to pass to each function (as with '2cleave',
'3cleave', etc).
The only downside of this form compared to the previous one is that
you need to explicitly group values if you want to return more than
one from one of the functions (except for the first). I don't see this
as a big problem.
- John