Search code examples
eachfactor-lang

Why does each behave differently inside word definitions?


To do a quotation for each in an array:

(scratchpad) { "3.1415" "4" } [ string>number ] each
3.1415 
4

To do this inside a word:

(scratchpad) : conveach ( x -- y z ) [ string>number ] each ;
(scratchpad) { "3.1415" "4" } conveach .

But this throws an error:

The word conveach cannot be executed because it failed to compile

The input quotation to “each” doesn't match its expected effect
Input             Expected         Got
[ string>number ] ( ... x -- ... ) ( x -- x )

What am I doing wrong?


Solution

  • Factor requires all words to have a known stack effect. The compiler wants to know how many items the word eats from the stack and how many it puts back. In the listener, the code you type in doesn't have that restriction.

    { "3.1415" "4" } [ string>number ] each
    

    Takes no items from the stack but puts two there. The stack effect would be denoted as ( -- x y ).

    [ string>number ] each 
    

    This code on the other hand, takes one item but puts 0 to many items back on the stack. The number varies depending on how long the sequence given to each is.

    ! ( x -- x y z w )
    { "3" "4" "5" "6" } [ string>number ] each
    ! ( x -- )
    { } [ string>number ] each 
    ! ( x -- x )
    { "2" } [ string>number ] each 
    

    You probably want to use the map word instead which would transform your sequence from one containing strings, to one containing numbers. Like this:

    : convseq ( strings -- numbers ) [ string>number ] map ;
    IN: scratchpad { "3" "4" } convseq .
    { 3 4 }