<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Feb 28, 2017 at 9:30 AM, M.-A. Lemburg <span dir="ltr"><<a href="mailto:mal@egenix.com" target="_blank">mal@egenix.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Here's an example similar to OCaml's lazy evaluation, which<br>
uses a simple lazy proxy object.<br>### OCaml like lazy evaluation<br>
class Lazy:<br>
    def __init__(self, code, frame):<br>
        self.code = code<br>
        self.globals = frame.f_globals<br>
        self.locals = frame.f_locals<br>
    def force(self):<br>
        return eval(self.code, self.globals, self.locals)<br></blockquote><div><br></div><div>This is a nice implementation.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">def log(level, b, c):<br>
    if level > 100:<br>
        return<br>
    if isinstance(c, Lazy):<br>
        c = c.force()<br>
    print ('%04i: %s' % (level, b % c))<br><br>
value = 1<br>
log(1000, 'Hello %i', lazy("expensive(value)"))<br>
log(10, 'Error %i', lazy("expensive(value)"))<br></blockquote><div><br></div><div>I agree this is very explicit.  It's also more code which has a minor smell to it.  In the hypothetical new construct I think it would look like this:</div><div><br></div></div></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div class="gmail_extra"><div class="gmail_quote"><div><font face="monospace, monospace">def log(level, b, c):</font></div></div></div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div class="gmail_extra"><div class="gmail_quote"><div><font face="monospace, monospace">    if level <= 100:</font></div></div></div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div class="gmail_extra"><div class="gmail_quote"><div><span style="font-family:monospace,monospace">        </span><span style="font-family:monospace,monospace">print ('%04i: %s' % (level, b % c))</span><br></div><div><span style="font-family:monospace,monospace"><br></span></div></div></div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div class="gmail_extra"><div class="gmail_quote"><div><span style="font-family:monospace,monospace">log(1000, 'Hello %i', delayed expensive(value))</span></div></div></div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div class="gmail_extra"><div class="gmail_quote"><div><span style="font-family:monospace,monospace">log(10, 'Error %i', delayed expensive(value))</span></div></div></div></blockquote><div class="gmail_extra"><div class="gmail_quote"><div><font face="monospace, monospace"> </font></div><div><font face="arial, helvetica, sans-serif">To me the second reads much better.  But indeed there <i>might be</i> surprises.  We might access the delayed object somewhere other than in the log() function (not in this example since it's not named, but in other cases).  Understanding where that happens adds to debugging work.</font></div></div><div class="gmail_extra"><br></div><div class="gmail_extra">Where I believe this is more important is for Dask-like code structures.  So perhaps I write:</div><div class="gmail_extra"><br></div></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div class="gmail_extra"><div class="gmail_extra"><font face="monospace, monospace">x = delayed expensive(1,2)</font></div></div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div class="gmail_extra"><div class="gmail_extra"><font face="monospace, monospace">y = delayed expensive(x,7)</font></div></div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div class="gmail_extra"><div class="gmail_extra"><font face="monospace, monospace">z = delayed expensive(x,y)</font></div></div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div class="gmail_extra"><div class="gmail_extra"><font face="monospace, monospace">w = delayed expensive(y,z)</font></div></div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div class="gmail_extra"><div class="gmail_extra"><font face="monospace, monospace">v = delayed expensive(w,x)</font></div></div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div class="gmail_extra"><div class="gmail_extra"><font face="monospace, monospace">print(z)</font></div></div></blockquote><div class="gmail_extra"><br></div><div class="gmail_extra">If I want to concretize `z` I don't want to do all the work of also concretizing `w` and `v` (but I need to do `x` and `y`).  In your explicit proxy approach, a lot of extra code is needed here.  But maybe Dask's spelling is perfectly fine:</div><div class="gmail_extra"><br></div><div class="gmail_extra"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div class="gmail_extra"><span style="font-family:monospace,monospace">from dask import delayed</span><br><div class="gmail_extra"><div class="gmail_extra"><font face="monospace, monospace">x = delayed(expensive)(1,2)</font></div></div><div class="gmail_extra"><div class="gmail_extra"><font face="monospace, monospace">y = delayed(expensive)(x,7)</font></div></div><div class="gmail_extra"><div class="gmail_extra"><font face="monospace, monospace">z = delayed(expensive)(x,y)</font></div></div><div class="gmail_extra"><div class="gmail_extra"><font face="monospace, monospace">w = delayed(expensive)(y,z)</font></div></div><div class="gmail_extra"><div class="gmail_extra"><font face="monospace, monospace">v = delayed(expensive)(w,x)</font></div></div><div class="gmail_extra"><div class="gmail_extra"><font face="monospace, monospace">print(z.compute())</font></div></div></div></blockquote><div><br></div>-- <br><div class="gmail_signature">Keeping medicines from the bloodstreams of the sick; food <br>from the bellies of the hungry; books from the hands of the <br>uneducated; technology from the underdeveloped; and putting <br>advocates of freedom in prisons.  Intellectual property is<br>to the 21st century what the slave trade was to the 16th.<br></div>
</div></div>