brick-lang / brick

The Brick language spec
University of Illinois/NCSA Open Source License
31 stars 0 forks source link

Pipeline syntax #10

Closed weswigham closed 10 years ago

weswigham commented 10 years ago
let | x = 1
    | y = 2
    | z = 3

This is nice. Why restrict it to let/cond/match? Why not let the | syntax, hereby referred to as the 'pipeline syntax' to any unary or binary function/operator?

Example use cases:

Binary operations:

sad -> |a:String, b:String|
    a+"\r\n"+b

sad | "Hello"
    | "from a new line"
let | x = + | func1()
            | func2()
            | func3()
zip | [1,3,5]
    | [2,4,6]

Unary operation:

process -> |q:Array<Int>|
    puts('[')
    let | sum = 0
    q.each -> |i:<Int>|
        sum += i
        puts | i
             | ','  
    puts | sum
         | ']'
    sum

process | [1,2,3]
        | [4,5,6]
        | [7,8,9]

On unary operation, the pipline applies the unary operation to every pipeline'd object.

On a binary operation, the pipeline acts as a kind of upwards collapse (or a fold left, if you'd prefer). The first two are fed as inputs to the binary operation, and then the result is fed into it again along with the third input, then that result is fed in along with the 4th, and so on.

So yeah, don't restrict this syntax to let/cond/match, it looks pretty useful and pretty elsewhere.

weswigham commented 10 years ago

Idea: Let there be a default functionality for pipelines (either apply or a foldl kinda deal), but let it be defined on a per-function basis using a :pipe metafunction (along the same lines as :before or :after) that is passed a list of the piped things. This means I could have something like

List<T> -> List<T> -> List<T>
def append(a, b)
    a.append(b)

List<List<T>> -> List<T>
def append:pipe(lst)
    ret = []
    lst.each -> |v|
        append(ret, v)
    ret

I like this idea.

toroidal-code commented 10 years ago

A single declaration, multiple application operator will be considered for v1.0.