godot lambdas do not capture by design

I learned this on stream today. I was trying to interrupt a coroutine by using a lambda:

func foobar():
    var stop = false
    var stop_callback = func():
            stop = true
    stop_signal.connect(stop_callback)
 
    await get_tree().create_timer(10).timeout
 
    print(stop) # Always false

The idea here is that I wanted to call foobar to kick off some animation (like playing 20 animations with a delay of 0.1 seconds between each one) and be able to call stop_signal.emit() to cancel the animation (like playing a different animation for the same objects). However, Godot does not capture local variables. Instead, it will copy the value of the local variable. This means that if you try to modify the local variable inside of the lambda, it will be as if you have a new variable with the same name.

I am shocked and horrified, but apparently this is by design.

One way to get around this is to use a variable which is normally copied by reference, like a Variant:

func foobar():
    var stop = { "value": false }
    var stop_callback = func():
            stop["value"] = true
    stop_signal.connect(stop_callback)
 
    await get_tree().create_timer(10).timeout
 
    print(stop["value"]) # Either true or false

Sure, that’s fine I suppose.