On 24 August 2015 at 11:41, Nick Coghlan <ncoghlan@gmail.com> wrote:
That's not very interesting if all you do is immediately call eval() on it, but it's a lot more interesting if you instead want to do things like extract the AST, dispatch the operation for execution in another process, etc. For example, you could use this capability to build eagerly bound closures, which wouldn't see changes in name bindings, but *would* see state changes in mutable objects.
Offering a nice early binding syntax is a question I've been pondering for years (cf. PEPs 403 and 3150), so I'm intrigued by this question of whether or not f-strings and i-strings might be able to deliver those in a way that's more attractive than the current options. This idea doesn't necessarily need deferred interpolation, so I'll use the current PEP 498 f-string prefix and substitution expression syntax. Consider the following function definition: def defer(expr): return eval("lambda: (" + expr + ")") We can use this today as a strange way of writing a lambda expression: >>> f = defer("42") >>> f <function <lambda> at 0x7f1c0314eae8> >>> f() 42 There's no reason to do that, of course - you'd just use an actual lambda expression instead. However, f-strings will make it possible for folks to write code like this: callables = [defer(f"{i}") for i in range(10)] "{i}" in that example isn't a one-element set, it's a substitution expression that interpolates "str(i)" into the formatted string, which is then evaluated by "defer" as if the template contained the literal value of "i" at the time of interpolation, rather than being a lazy reference to a closure variable. (If you were to get appropriately creative with exec, you could even use a trick like this to define multiline lambdas) Regards, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia