On Sat, Oct 23, 2021, 11:28 PM Chris Angelico <rosuav@gmail.com> wrote:
> So stawman proposal:
>
>   def fun(seq, low=0, high=defer: len(seq)):
>       assert low < high
>       # other stuff...
>
> Where the implication here is that the "defer expression" creates a dynamic scope.

At what point is this defer-expression to be evaluated? For instance:

def f(x=defer: a + b):
    a, b = 3, 5
    return x

Would this return 8, or a defer-expression? If 8, then the scope isn't truly dynamic, since there's no way to keep it deferred until it moves to another scope. If not 8, then I'm not sure how you'd define the scope or what triggers its evaluation.

This would return 8. 

Basically as if the expression were passed as a string, and `eval(x)` were run when the name "x" was looked up within a scope.

An elaboration of this strawman could allow partial binding at the static scope as well. E.g.

cursor = db_connection.cursor()
table = "employees"
expensive_query = defer c=cursor, t=table: c.execute(
    f"SELECT * FROM {t} WHERE name={name}")

def employee_check(q=expensive_query):
    if random.random() > 0.5:
        name = "Smith"
        return q

So 'c' and 't' would be closed over when the deferred is defined, but 'name' would utilize the dynamic scope. In particular, the expensive operation of resolving the deferred would only occur if it was needed.