PEP-308 a "simplicity-first" alternative
Bengt Richter
bokr at oz.net
Fri Feb 14 01:28:15 EST 2003
On Thu, 13 Feb 2003 04:44:43 -0700, Steven Taschuk <staschuk at telusplanet.net> wrote:
>Quoth Erik Max Francis:
> [on Bengt Richter's {x} proposal]
>> So can you rigorously define the behavior of an expression with {}
>> markers in the general case? Can you even rigorously define it here?
>> What happens when it appears somewhere other than one of the operands to
>> a logical operator, what then? Can you even fully define its semantics?
>
>As I read Richter's proposal, {expr} would be an object such as
No, this leads down another path with different semantics.
> class braced:
> def __nonzero__(self):
> return 1
> def __getattr__(self, name):
> return (lambda: expr)().__getattr__(name)
> def __setattr__(self, name, value):
> return (lambda: expr)().__setattr__(name, value)
>That is, an object which delegates to the value of expr for
>everything except __nonzero__. (One outstanding question in this
>interpretation is whether, e.g., {expr}.__class__ should refer to
>expr's class or the braced object's.)
>
>Note that expr above is not a variable named 'expr', but a
>metasyntactic variable for an arbitrary expression. The lambdas
>thus accomplish lazy evaluation, whence the desired short-
>circuiting behaviour in the context "x and {y} or z". As written
>above they also allow {expr} to change value:
> >>> x = 3
> >>> y = {x+1}
> >>> print y
> 4
> >>> x += 1
> >>> print y
> 5
>Memoizing the result of (lambda: expr)() would avoid this, but
>we'd still get:
> >>> x = 3
> >>> y = {x+1}
> >>> x += 1
> >>> print y
> 5
>(Since, by design, expr would not be evaluated until the first
>invocation of a method other than __nonzero__.)
>
>If memory serves, Richter mentioned that 'or' would "unwrap" the
>braced object, presumably to prevent it from being passed around
>the program and wreaking havoc. But if used in contexts other
>than the and/or ternary conditional idiom, braced values introduce
>fragility into all sorts of code:
You are describing "braced" according to your interpretation, not my semantics.
> x = []
> y = { map(somefunction, x) }
The fact that you are binding y here means that you must bind to the _value_
wrapped inside the {}, and you get that by evaluating the expression. Thus the
above just has the same effect as
y = map(somefunction, x)
> # ... 50 lines of code fiddling with x, occasionally
> # looking at y to find out what x's data maps to
> # under somefunction ...
> if y: # intended to mean "if y is nonempty"
The intention is fine. The {} was peeled off above, when evaluated for binding to y.
> print y[0] # possible IndexError
No error -- it should work just as intended.
>(This example is not entirely silly: it could be rewritten with "y
>= lambda: map(somefunction, x)", and "y()" instead of "y"
No, there is no deferral of evaluation of the {x} term once the term
is reached to be evaluated for its normal value. This happens when it
is used in a logical context as well as non-logical. The difference is
that logical true is substituted for whatever the logical value would
have been. The non-logical value is then immediately the value that continues
as such, just as for an unwrapped value.
>thereafter, but the coder might prefer these newfangled braces for
>their terseness.)
>
>Many of these complexities can be avoided by permitting these
>braces only in unwrapping contexts. In this scenario, they're
Any context that takes the value unwraps it. It's just that in
a logical context, the logical value is True. Note that in a logical
context this two-step access of logical value and normal/unwrapped value
already occurs. E.g., "[] and x" results in [], not 0.
>much more like an inflection of those contexts than a way of
>creating an object with a weird truth value (since the putative
>object would only ever be accessible to the unwrapping context).
Every non-boolean object is "an object with a weird truth value"
and has to be treated correctly according to context ;-)
>Then the fact that the braces look like some kind of operation on
>or container for the enclosed expression is misleading, and a
>separate, more perspicuous, syntax for those contexts would be
>preferable.
This can be a workable way to look at it.
>
>That leaves us back where we started, seeking a clear syntax for
>the ternary conditional.
Yup ;-)
Regards,
Bengt Richter
More information about the Python-list
mailing list