Re: Code block literals
Dave Benjamin wrote:
[color=blue]
> Alex Martelli wrote:[color=green]
>> The only annoyance here is that there is no good 'literal' form for
>> a code block (Python's lambda is too puny to count as such), so you
>> do have to *name* the 'thefunc' argument (with a 'def' statement --
>> Python firmly separates statements from expressions).[/color]
>
> Here's my non-PEP for such a feature:
>
> return { |x, y|
> print x
> print y
> }
>
> Which would be the equivalent of:
>
> def anonymous_funct ion(x, y):
> print x
> print y
> return anonymous_funct ion[/color]
Oh, and what should:
return {
}
MEAN? An empty dictionary, like today, or the equivalent of
return lambda: None
i.e. an empty argument-less function?
This is just reason #1 why this syntax is not satisfactory (I
guess it could be forced by mandating || to mean "takes no
args" -- deviating from Ruby in that sub-issue, though). The
second point is the use of punctuation in a way that no other
Python syntactic context allows -- it really feels alien.
Further, something that is more often than not desired by
people who desire code blocks is that they *don't* start a
new scope. Ruby fudges it with an ad-hoc rule -- use of
variables already existing outside is "as if" you were in
the same scope, use of new variables isn't (creates a new
variable on each re-entry into the block via yield, right?).
Clearly we can't use that fudge in Python. So, this is a
semantic problem to solve for whatever syntax. Can we find
any approach that solves ALL use cases? I don't know, but my
personal inclination would be to try saying that such a block
NEVER define a new lexical scope, just like list comprehensions
don't -- i.e. in this sense such blocks would NOT be at all
equivalent to the functions produced by a def statement (lots
of implementation work, of course) -- all variables that might
look like locals of such a block would instead be considered
locals of the "enclosing" scope (which isn't enclosing, in a
sense, as there's no other new scope to enclose...;-).
SOME explicit termination is no doubt necessary if we want to
allow returning e.g. a tuple of two or more such functions --
which is why we can't try taking another (and less repellent
to Pythonic syntax) leaf from Ruby's book (using do instead
of { -- requires making do a keyword -- and leaving out the
end that Ruby always requires, of course):
return do(x, y):
print x
print y
there would be no way to write something more after this
block but within the same expression if the only termination
was dedenting; perhaps:
return ( do(x, y):
print x
print y
), ( do(x, y):
print y
print x
)
i.e. with parentheses around the do-expression (if you need
to put anything more after it) might help here.
[color=blue]
> Then, merge map, filter, and reduce into the list type, so we can play[/color]
Why? So you can't e.g. reduce an arbitrary iterator (e.g., genererator),
tuple, array.array, ..., any more? We'd be better off without them, IMHO.
I see no advantage, over e.g. itertools, in associating these syntactically
to sequences (any kind or all kinds) or even iterators.
Alex
Dave Benjamin wrote:
[color=blue]
> Alex Martelli wrote:[color=green]
>> The only annoyance here is that there is no good 'literal' form for
>> a code block (Python's lambda is too puny to count as such), so you
>> do have to *name* the 'thefunc' argument (with a 'def' statement --
>> Python firmly separates statements from expressions).[/color]
>
> Here's my non-PEP for such a feature:
>
> return { |x, y|
> print x
> print y
> }
>
> Which would be the equivalent of:
>
> def anonymous_funct ion(x, y):
> print x
> print y
> return anonymous_funct ion[/color]
Oh, and what should:
return {
}
MEAN? An empty dictionary, like today, or the equivalent of
return lambda: None
i.e. an empty argument-less function?
This is just reason #1 why this syntax is not satisfactory (I
guess it could be forced by mandating || to mean "takes no
args" -- deviating from Ruby in that sub-issue, though). The
second point is the use of punctuation in a way that no other
Python syntactic context allows -- it really feels alien.
Further, something that is more often than not desired by
people who desire code blocks is that they *don't* start a
new scope. Ruby fudges it with an ad-hoc rule -- use of
variables already existing outside is "as if" you were in
the same scope, use of new variables isn't (creates a new
variable on each re-entry into the block via yield, right?).
Clearly we can't use that fudge in Python. So, this is a
semantic problem to solve for whatever syntax. Can we find
any approach that solves ALL use cases? I don't know, but my
personal inclination would be to try saying that such a block
NEVER define a new lexical scope, just like list comprehensions
don't -- i.e. in this sense such blocks would NOT be at all
equivalent to the functions produced by a def statement (lots
of implementation work, of course) -- all variables that might
look like locals of such a block would instead be considered
locals of the "enclosing" scope (which isn't enclosing, in a
sense, as there's no other new scope to enclose...;-).
SOME explicit termination is no doubt necessary if we want to
allow returning e.g. a tuple of two or more such functions --
which is why we can't try taking another (and less repellent
to Pythonic syntax) leaf from Ruby's book (using do instead
of { -- requires making do a keyword -- and leaving out the
end that Ruby always requires, of course):
return do(x, y):
print x
print y
there would be no way to write something more after this
block but within the same expression if the only termination
was dedenting; perhaps:
return ( do(x, y):
print x
print y
), ( do(x, y):
print y
print x
)
i.e. with parentheses around the do-expression (if you need
to put anything more after it) might help here.
[color=blue]
> Then, merge map, filter, and reduce into the list type, so we can play[/color]
Why? So you can't e.g. reduce an arbitrary iterator (e.g., genererator),
tuple, array.array, ..., any more? We'd be better off without them, IMHO.
I see no advantage, over e.g. itertools, in associating these syntactically
to sequences (any kind or all kinds) or even iterators.
Alex
Comment