<div dir="ltr"><div>Proposal: Light-weight call-by-name syntax in Python</div><div><br></div><div>  The following syntax</div><div>     a : b</div><div>  is to be interpreted as:</div><div>     a(lambda: b)</div><div><br></div><div>Effectively, this gives a "light-weight macro system" to Python,</div><div>since it allows with little syntax to indicate that the argument to</div><div>a function is not to be immediately invoked.</div><div><br></div><div>It is a generalization of special-case syntax proposals like</div><div> delayed: <expr></div><div>In this proposal, `delayed' can be a normal callable.</div><div><br></div><div>Motivating examples follow:</div><div><br></div><div># Logging</div><div># The following assumes the logging library has been extended to support</div><div># a callable argument in addition to a string.</div><div><br></div><div>import logging</div><div>logging.debug: "I have a %s" % expensive_function()</div><div><br></div><div># Spawn parallel tasks</div><div># This would work with the existing concurrent.futures unmodified.</div><div><br></div><div>from concurrent.futures import ThreadPoolExecutor</div><div>executor = ThreadPoolExecutor(max_workers=4)</div><div>future = executor.submit: some_long_running_function(another_long_one())</div><div><br></div><div># Asyncio</div><div><br></div><div>loop.call_soon_threadsafe: do_something(42)</div><div><br></div><div># Custom asserts</div><div><br></div><div>from some_module_implementing_contracts import precondition</div><div><br></div><div>def foo(x):</div><div>    precondition: x >= 0</div><div>    return math.sqrt(x)</div><div><br></div><div><br></div><div># Lazy evaluation</div><div><br></div><div>class delayed:</div><div>    def __init__(self, callback):</div><div>        self.callback = callback</div><div>        self.value = None</div><div><br></div><div>    def __call__(self):</div><div>        if self.callback is not None:</div><div>            self.value = self.callback()</div><div>            self.callback = None</div><div>        return self.value</div><div><br></div><div>promise = delayed: a() + b()</div><div>print(promise())</div><div><br></div><div><br></div><div># default dictionary</div><div><br></div><div>dd = collections.defaultdict: MyDefaultObject(42)</div><div>print(dd["foo"]) </div><div># => prints MyDefaultObject(42)</div><div><br></div><div><br></div><div>Notes on syntax:</div><div>a : b is my preferred syntax.</div><div>It would conflict with existing use of : in a few places, e.g.</div><div>in if and while. My preferred approach is that we would</div><div>need to write (a : b) there.</div><div><br></div><div>An alternative is a as-yet-unused token such as :: .</div><div><br></div><div>Stephan</div></div>