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 later).
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 the suite.
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 compatibility).
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 synchronisation idea.
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 :-)