https://codeberg.org/fakefred/wikt-cli/src/branch/pipes
loc nearly tripled, so has cursedness
nevertheless, having fun implementing pipes with #python
also just so that you're aware, if you do
def out_func():
funcs = []
for x in [0, 1]:
var = x
def in_func():
return var
funcs.append(in_func)
return funcs
print([f() for f in out_func()])
this looks like it's gonna print [0, 1] but it's not. It's gonna give you [1, 1]. #python
@fakefred always a classic
@trickster @fakefred Just checking I understand: this might work properly if out_func was a generator rather than returning a list right?
@padraic_padraic @fakefred this happens because of the operational semantics in Python
def out_func():
funcs = []
for x in [0, 1]:
def in_func():
return x
funcs.append(in_func)
return funcs
`in_func` is a closure that closes over the `x` reference
every iteration in the `for` modifies `x` in place, it does not create a new `x` binding, so, of course, because all created closures point to the same x, the last version of x is the one that is returned, always
@trickster @fakefred Perfect explanation, thankee tricky
@padraic_padraic @fakefred but wait, there's more!
default arguments for functions are captured on the spot, so this piece of code can actually be made to work like this:
def out_func():
funcs = []
for x in [0, 1]:
def in_func(x=x):
return x
funcs.append(in_func)
return funcs
print([f() for f in out_func()])
# => [0, 1]
@trickster @fakefred Ah yeah, that I've heard of, because of this wild behaviour: https://nikos7am.com/posts/mutable-default-arguments/
Which soem people abuse to add memoisation
@padraic_padraic @fakefred lmao, that's horrible, just make a @ memo decorator
@trickster @fakefred I mean yeah, it's even part of functools these days if you absolutely must, functools.lru_cache.
@padraic_padraic @fakefred oh, it's what the article says, ok, ok, that's mighty fine
@padraic_padraic @fakefred this will work because (x=x) forces x to be "followed", we are technically not closing over it anymore, so x being a value type in this case, it's simply copied over
if x was a reference type, you would still be pointing to the same object in all closures
@padraic_padraic @fakefred this applies to any variable created or mutated inside of the `for`, because all vars are reused at every iteration