> Maybe we can change the syntax back to something that started this.
> Instead of the xdef keyword, we'd use a colon at the end of an
> expression or assignment line. The grammar could be e.g.
> statement: (variable '=')* expression [':' suite]
> (Where suite is a simple statement or NEWLINE INDENT block DEDENT.)
OK, that's the grammar. But what's the semantics? I can infer some
of it from the examples below, but I can't generalise it.
Let's start with some specifics:
You're *only* proposing this extension (the : suite) for expression and
assignment statements, yes? Specifically, from the current grammar,
"expression_statement" and "assignment_statement". No augmented
assignments? I can't see the use for
var += expr : suite
but someone's going to (ab)use it if it's available.
On the other hand, what about destructuring assignments?
v1, v2, v3 = expr : suite
It's not at all clear what that would mean... (Or maybe it is, see
If you're looking solely at the case you state above, that becomes
a completely new grammar rule (which overlaps a lot of others). For
a more explicit rule, you want
guido_statement: (variable '=')* expression ':' suite
which is a compound (rather than simple) statement in the grammar.
I consider it a bad sign that I can't think of an obvious name for
this construct :-)
> Then the locking example could be written as
> This would mean
> where thunk would be a callable representing the block as before.
OK, so the semantics are that
expr : suite
requires expr to be a callable of a single argument, and calls that
callable, passing it *another* callable whose effect is to execute
That's not unreasonable, but you'd need to handle errors (most likely
that expr isn't the right type of value) very carefully, or nobody's
going to understand what went wrong :-)
> If a variable was present it would receive the result, so that e.g.
> foo = property:
> def get(self): ...
> would end up meaning
> foo = property(thunk)
> which is only a very small stretch from what property currently does
> (it would have to do a typecheck on its argument for backwards
But this isn't compatible with your previous example! If thunk is a
callable which encapsulates the suite, then in this case, you need
foo = property(*thunk())
and you need the suite to end explicitly with a return statement,
returning a tuple of values for the argument to property(). Unless
you are suggesting letting property() do something different when
called with a single argument which is a callable. I don't like that,
it's too magical.
The more I think about it, the less I like it. Basically, it's under-
specified. You can give examples showing "how" you can use the syntax
to solve lots of problems, but when you try to unify the examples,
the edge cases don't match.
The advantage of Samulele's proposal is that the semantics was explicit,
by defining the equivalent code. I also liked the fact that the suite
was "just evaluated", and the user code got passed the resulting
environment - it meant you didn't have to remember to add "return"
statements. But on the other hand, it meant you couldn't control *when*
the thunk was executed (to wrap try...finally round it, or to do
conditional or repeated execution). So it's not useful for your
There are two separate requirements here - a syntax for property
definitions, and a synchronised block construct (which can easily be
generalised to cover most forms of acquire/release requirements). I'm
not at all sure it's valid to try to make a general construct which
satisfies both requirements.
... And actually, I'm much less bothered about properties than about
acquire/release. I use neither a lot, but I find the current situation
more bothersome for acquire/release. At some point we really *must* get
this thread split into separate issues, if only to give Brent a fighting
chance when summarising :-)