Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

grab expressions #316

Closed
bvssvni opened this issue Jun 24, 2016 · 0 comments
Closed

grab expressions #316

bvssvni opened this issue Jun 24, 2016 · 0 comments

Comments

@bvssvni
Copy link
Member

bvssvni commented Jun 24, 2016

A grab expression computes a value inside a closure that depends on variables in the closure environment. It can also be used to precompute data at top level (more about this later).

Example:

fn main() {
    a := sift i 3 { \(x) = x + grab i } // Compute the value of `i` inside closure
    for i {
        println(\a[i](0))
    }
}

A grab expression is evaluated when the closure is created and inserted into the AST of the closure variable. You can use any expression, as long as it returns a value:

grab i * 5 + 2 // OK
grab println("hi") // ERROR: Expected something, found `void`

It can not depend on any variable of the closure itself. Variables with same name will be reported as an error:

x := 2
a := \(x) = x + grab x // ERROR: Grabbed `x` has same name as closure variable

You can print out a closure to view the result of grab expression:

fn main() {
    a := \(x: f64) = x + grab prod i 3 { i + 1 }
    println(a) // prints `\(x: f64) = x + 6`
    println(\a(0)) // prints `6`
}

An error is shown if you try to use a grab expression outside a closure:

fn main() {
    a := grab 1 + 1
    println(a)
}
 --- ERROR --- 
main (source/test.dyon)

`grab` expressions must be inside a closure
2,15:     a := grab 2
2,15:               ^

Grabbing higher levels

A closure inside a closure can contain a grab expression that computes values 1, 2 or higher levels:

a := \(x) = \(y) = \(z) = z + (grab y) + (grab '2 x)

Remember to use parenthesis (grab <expr>) if you are using multiple grab statements within same expression.

Thumb rule: The grab expression with highest level gets evaluated first.

Evaluation order

Blocks are evaluated after higher level expressions, such as in if expressions, where the conditions are evaluated before blocks:

fn main() {
    a := 5
    b := \(x) = if x {
        grab {
            println("two")
            a
        }
    } else if x < grab {
        println("one")
        a - 2
    } {
        grab {
            println("three")
            a + 1
        }
    }
    // one
    // two
    // three
    // prints `\(x: any) = if x { 5 } else if x < 3 { 6 }`
    println(b)
}

Otherwise, the evaluation follows top-down as you normally expect the code to be executed.

Precomputing data at top level

One can also use grab to precompute at top level. This is often used when the script is called frequently, e.g. to generate audio.

fn main() {
     a := grab [1, 2, 3]  // Will be precomputed when loading script
}

The following data can be precomputed:

  • Array fill, e.g. [false; 24]
  • Array, e.g. [1, 2, 3]
  • Object, e.g. {a: 1, b: 2}
  • 4D vector, e.g. (1, 2, 3, 4)
  • Link structure, e.g. link {1 "hi" false}

The data structures can be nested, e.g. [[1, 2], [3, 4]] or [{a: 1, b: 3}, {a: 2, b: 4}].

Since the grab expression at top level injects the variable into the AST, when you mutate the variable Dyon will use copy-on-write. This means that grab expressions at top level is slower when mutating the variable, but faster when only reading from it.

Motivation

Adds a non-state capture ability of variables in the environment of closures. It is more powerful in the way that it works as a partial evaluation operator, but less flexible than mutable captured variables.

Dyon uses current objects for mutating the environment, so there is less need for capturing mutatable variables. A non-state capture is easier to reason about, requires no lifetime, and does not add overhead when calling closures.

@bvssvni bvssvni changed the title Capture value of expressions in closures with capt keyword Capture value of expressions in closures with grab keyword Jun 24, 2016
@bvssvni bvssvni changed the title Capture value of expressions in closures with grab keyword grab keyword Jun 24, 2016
@bvssvni bvssvni changed the title grab keyword grab expressions Jun 24, 2016
This was referenced Jun 26, 2016
@bvssvni bvssvni removed the draft label Jul 11, 2016
@bvssvni bvssvni closed this as completed Jul 11, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant