expression form of one-to-many dict?

Bengt Richter bokr at oz.net
Mon Dec 20 05:25:32 CET 2004


On Sun, 19 Dec 2004 21:29:27 +0100, "Fredrik Lundh" <fredrik at pythonware.com> wrote:

>Mike Meyer wrote:
>
>> Personally, I'd love a language feature that let you create a function
>> that didn't evaluate arguments until they were actually used - lazy
>> evaluation. That lets you write the C ?: operator as a function, for
>> a start.
>>
>> Hmmm. No, iterators can't be used to fake it. Oh well.
>
>if you can get some collaboration from the function itself, you can fake
>anything:
>
>def foo_default():
>     while 1:
>          print "MAKE A FOO"
>          yield "foo"
>foo_default = foo_default()
>
>class mydict(dict):
>     def setdefault(self, key, default=None):
>          try:
>               return self[key]
>          except KeyError:
>               if hasattr(default, "next"):
>                    default = default.next()
>               self[key] = default
>               return default
>
>d = mydict()
>d["spam"] = "bacon"
>
>print d.setdefault("spam", foo_default)
>print d.setdefault("egg", foo_default)
>
Just the same, it would be interesting to be able to create special-form style functions easily
by designating arbitrary arguments for deferred evaluation, to which eval could safely be applied
(or maybe a restricted unquote_arg function for better safety).
E.g., double back-tick is a syntax error now, so you could write

    def ternary(c, ``t, ``f):
        if c: return eval(t)
        else: return eval(f)

(Of course, it's also interesting to speculate about what kind of first class object
would be returned by
    def foo(``x): return x
and whether ``x should be a generally valid expression, not just specialized for arg list setup ;-)

(note that ``x is not quite the same as automated lambda:x -- nor lambda x=x:x -- wrapping,
since the latter would evaluate x for the lambda and the former accesses the last value set
in the closure cell:

 >>> def foo():
 ...     v = 'a'
 ...     x = lambda:v
 ...     v = 'b'
 ...     y = lambda:v
 ...     return x,y
 ...
 >>> [foo()[i]() for i in (0,1)]
 ['b', 'b']

Anyway, with a suitable `` quoting operator your setdefault could be

    def setdefault(self, key, ``default=None):
        ...
            default = eval(default)
            ... etc

BTW, note that

    def foo(``default=expr): ...

and

    def foo(``default=``expr): ...

could mean different things, depending on preferred semantics and ``expr as
a generally valid expression.

Regards,
Bengt Richter



More information about the Python-list mailing list