On Fri, May 29, 2020 at 7:05 PM David Mertz <mertz@gnosis.cx> wrote:
On Fri, May 29, 2020 at 3:19 AM Stephen J. Turnbull <turnbull.stephen.fw@u.tsukuba.ac.jp> wrote:
    # Just too ugly for me!
    def foo(x=lambda: random.randint(0,9)):

        x = x()
        # ...

I think this is a perfect example of where my desired "delayed" (or "deferred") construct would be great.  There are lots of behaviors that I have not thought through, and do not specify here.  But for example:

def foo(a=17, b=42,, x=delayed randint(0,9), y=delayed randrange(1,100)):
    if something:
        # The simple case is realizing a direct delayed
        val = concretize x
    elif something_else:
        # This line creates a call graph, not a computation
        z = ((y + 3) * x)**10
        # Still call graph land
        w = a / z
        # Only now do computation (and decide randoms)
        val = concretize w - b

But if I understand correctly, a delayed value is concretized once, then the value is cached and remains concrete. So if we still have early binding, then x will only have one random value, unlike Stephen's lambda which generates a new value each time it's called.