DisplayScript

Dynamic Bindings

Dynamic bindings let you pass values through your program without using function arguments.

For example, say you have a button drawable:

drawable button(str) {
    draw fill(srgb(0.7, 0.7, 0.9))
    draw centered(text(str))
}

You use buttons throughout your program:

drawable button(str) {
    draw fill(srgb(0.7, 0.7, 0.9))
    draw centered(text(str))
}
drawable bottomBar {
    var itemWidth = @width / 4
    var x = 0
    for i in range(1, 5) {
        draw at(x, 0, itemWidth, @height, inset(5, button("\(i)")))
        x = x + itemWidth
    }
}
draw at(0, 60, @width, 100, inset(18, button("Start")))
draw at(0, 160, @width, 100, inset(18, button("Exit")))

var barHeight = 100
draw at(0, @height - barHeight, @width, barHeight, bottomBar)

Now you want different buttons to have different colors. Maybe the exit button should have a different color than the others. One way to do this is by adding a color argument to button:

drawable button(str, color) {
    draw fill(color)
    draw centered(text(str))
}

but then you'd have to update all the places that call button to also pass in a color. You'd need to pass a color to bottomBar, too—otherwise, how would it know what color its buttons should be?

Dynamic binding offers a more convenient solution. We can add a dynamic binding called buttonColor:

dynamic var buttonColor = srgb(0.7, 0.7, 0.9)
drawable button(str) {
    draw fill(buttonColor)
    draw centered(text(str))
}

Normally, after bindings are captured by functions, the captured value cannot change. Dynamic bindings, however, continue to change after being captured:

// Remove the "dynamic" keyword here to see how the behavior differs.
dynamic var buttonColor = srgb(0.7, 0.7, 0.9)
drawable button(str) {
    draw fill(buttonColor)
    draw centered(text(str))
}
buttonColor = red
draw button("test")

Assignments to dynamic bindings still respect scope, though. Assignments only last until the end of the function or drawable they occur in:

dynamic var buttonColor = srgb(0.7, 0.7, 0.9)
drawable button(str) {
    draw fill(buttonColor)
    draw centered(text(str))
}
drawable bottomBar {
    var itemWidth = @width / 4
    var x = 0
    for i in range(1, 5) {
        draw at(x, 0, itemWidth, @height, inset(5, button("\(i)")))
        x = x + itemWidth
    }
}
drawable exitButton {
    buttonColor = red
    draw button("Exit")
}
draw at(0, 60, @width, 100, inset(18, button("Start")))
draw at(0, 160, @width, 100, inset(18, exitButton))

var barHeight = 100
draw at(0, @height - barHeight, @width, barHeight, bottomBar)

Notice how assigning buttonColor to red only affects the exitButton drawable, not the normal buttons drawn afterward.