Bengt Richter wrote:
Problems? (Besides NIH, which I struggle with regularly, and had to overcome to 
accept Tim's
starting point in this ;-)

The ideas regarding creating blocks whose name bindings affect a different scope are certainly interesting (and relevant to the 'using' out-of-order execution syntax as well).


Out-of-order execution appeals to me, but the ability to flag 'hey, this is just setup for something I'm doing later' might be a reasonable alternative (particularly with the affected names highlighted on the first line). As Jeff pointed out, it would be significantly less surprising for those encountering the construct for the first time. Folding code editors would be able to keep the setup clause out of the way if you really wanted to hide it.

On the other hand, it might be feasible to construct a virtually identical out-of-order two suite syntax, similar to the mathematical phrasing "let f = c/lambda where f is the frequency, c is the speed of light and lambda is the wavelength". Either way, you've convinced me that two suites (and a new compound statement), as well as specifying which names can be rebound in the containing scope, is a better way to go than trying to mess with the definition of Python statements.

On keywords, while 'let' is nice for assignments, I find it just doesn't parse properly when I put function or class definitions in the clause. So, I'll swap it for 'use' in the examples below. The statement could then be read "use these outer bindable names, and this additional code, in this suite". YMMV, naturally.

Let's consider some of the examples given for 'where' using an in-order let/in type syntax (the examples only bind one name at a time, but would allow multiple names):

# Anonymous functions
use res:
  def f(x):
    d = {}
    exec x in d
    return d
in:
  res = [f(i) for i in executable]

# Declaring properties
class C(object):
  use x:
    def get(self):
      print "Demo default"
    def set(self, value):
      print "Demo default set"
  in:
    x = property(get, set)

# Design by contract
use foo:
  def pre():
    pass
  def post():
    pass
in:
  @dbc(pre, post)
  def foo():
    pass

# Singleton classes
use C:
  class _C:
    pass
in:
  C = _C()

# Complex default values
use f:
  def default():
    return "Demo default"
in:
  def f(x=default()):
    pass

They actually read better than I expected. Nicely, the semantics of this form of the syntax *can* be articulated cleanly with current Python:

use <names>: <use-suite>
in: <in-suite>

as equivalent to:

def __use_stmt():
  <use-suite>
  def _in_clause():
    <in-suite>
    return <names>
  return _in_clause()
__use_stmt_args = {}
<names> = __use_stmt()
del __use_stmt

Those semantics don't allow your switch statement example, though, since it doesn't use any magic to write to the outer scope - it's just a normal return and assign.

However, I don't think starting with these semantics would *preclude* adding the ability to name the second block at a later date, and make the name rebinding part of executing that block - the standard usage doesn't really care *how* the names in the outer scope get bound, just so long as they do. Whether I think that's a good idea or not is an entirely different question :)

Another aspect to consider is whether augmented assignment operations in the inner-scopes should work normally - if so, it would be possible to alter the semantics to include passing the existing values as arguments to the inner scopes.

Moving on to considering a two-suite out-of-order syntax, this would have identical semantics to the above, but a syntax that might look something like:

as <names>: <in-suite>
using: <use-suite>

# Anonymous functions
as res:
  res = [f(i) for i in executable]
using:
  def f(x):
    d = {}
    exec x in d
    return d

# Declaring properties
class C(object):
  as x:
    x = property(get, set)
  using:
    def get(self):
      print "Demo default"
    def set(self, value):
      print "Demo default set"

# Design by contract
as foo:
  @dbc(pre, post)
  def foo():
    pass
using:
  def pre():
    pass
  def post():
    pass

# Singleton classes
as C:
  C = _C()
using:
  class _C:
    pass

# Complex default values
as f:
  def f(x=default()):
    pass
using:
  def default():
    return "Demo default"

Cheers,
Nick.

--
Nick Coghlan   |   [EMAIL PROTECTED]   |   Brisbane, Australia
---------------------------------------------------------------
            http://boredomandlaziness.skystorm.net
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to