Search code examples
arraystuplesfactor-lang

Simplifying boa constriction through destructuring arrays?


Very often I find myself in a situation like this:

IN: scratchpad: TUPLE: box
                    length width height ;

IN: scratchpad { { 1 2 3 } { 4 5 6 } { 6 7 8 } }

--- Data stack:
{ ~array~ ~array~ ~array~ }
IN: scratchpad [ V{ } clone-like ] dup [ map ] dip call

--- Data stack:
V{ ~vector~ ~vector~ ~vector~ }
IN: scratchpad [ dup pop swap dup pop swap dup pop swap drop box boa ] map  

--- Data stack:
V{ ~box~ ~box~ ~box~ }
IN: scratchpad dup .
V{
    T{ box { length 3 } { width 2 } { height 1 } }
    T{ box { length 6 } { width 5 } { height 4 } }
    T{ box { length 8 } { width 7 } { height 6 } }
}

Which achieves the result I want, but this:

dup pop swap

Must be copy/pasted the same number of times as items in the array I want to destruct, and the array must first be clone-liked to a V{ } vector, and... it's just really terrible, messy code. (Note that 3 [ dup pop swap ] times will not work because of the stack effect.)

There must be a better way to construct an instance of a TUPLE from the items of an array. What is it?


Solution

  • Note you can unpack many elements at a time from sequences with first2, first3 and first4 in sequences and x firstn from sequences.generalizations.

    I think most "Factorish" way of doing it is defining a constructor that takes a sequence as argument:

    : seq>box ( s -- box ) first3 box boa ;
    

    Then you can map on it:

    { { 1 2 3 } { 4 5 6 } } [ seq>box ] map
    

    Other way, closer to what you're doing:

    { { 1 2 3 } { 4 5 6 } } [ box prefix >tuple ] map
    

    >tuple takes a sequence of the form

    { name-of-tuple-class 1st-slot-value 2nd-slot-value ... last-slot-value }
    

    so you have to prefix each sequence with the class.