Quick and Dirty FLOW Example

At one point I proposed something along the lines of:

>> flow [
       [1 2 3]
       reverse _
       map-each x _ [x * 10]
   ]
== [30 20 10]

Seems Neat. How Hard Is It To Do?

Well, let's just be simple-minded to start.

(and let's use the up-and-coming notation, just to start getting used to it...as well as my proposed change to REPLACE to mean REPLACE/ALL by default...)

flow: func [
    block [block!]
    :placeholder [element?]
    <local> flow-result
][
    placeholder: default [_]
    block: copy block
    replace block placeholder $flow-result
    while [not tail? block] [
         insert block $flow-result:
         [block flow-result]: evaluate:next block
    ]
    return flow-result
]

And On This Example, It Works!

Not with the new notation quite yet, but with the slash-as-refinement notation. Some notes:

  • element? means any non-antiform

  • $flow-result evaluates to the plain word of flow-result, but carrying a binding from the current context (in this case, so that the code in the user supplied block can see the local variable in FLOW's frame)

But How Does It Work?

It simply creates a variable FLOW-RESULT, and then splices it into a copy of the block:

flow [
    [1 2 3]
    reverse _
    map-each x _ [x * 10]
]
=>
[
   flow-result: [1 2 3]
   flow-result: reverse flow-result
   flow-result: map-each x flow-result [x * 10]
]

But it can't do it ahead of time, because it doesn't know the span of the expressions until it executes them. So it goes one step at a time, inserting the SET-WORD! after each step

[
   flow-result: [1 2 3]  ; <-- gets to here
   reverse flow-result
   map-each x flow-result [x * 10]
]
...
[
   flow-result: [1 2 3]
   flow-result: reverse flow-result  ; <-- gets to here
   map-each x flow-result [x * 10]
]
...
[
   flow-result: [1 2 3]
   flow-result: reverse flow-result
   flow-result: map-each x flow-result [x * 10]  ; finished
]

Very Simple, But Useful Right Off The Bat

I don't know what all design the correct FLOW would need. It would need to do its replacements deeply (we don't have REPLACE/DEEP, so you'd have to use PARSE or something).

And I don't know what features it should have. But... pretty cool to see this kind of thing be so natural to do.

1 Like

Syntax suggestion: I don’t particularly like <$> to denote the hole. I’d suggest _ instead (which is what you already suggested for POINTFREE / PARTIAL, so it’s consistent). Naturally, it should be configurable via a refinement.

1 Like