Hi.
It would be great to be able to reverse usage/definition parts in
haskell-way with "where" keyword. Since Python 3 would miss lambda, that
would be extremly useful for creating readable sources.
Usage could be something like: res = [ f(i) for i in objects ] where: def f(x): #do something
or
print words[3], words[5] where: words = input.split()
- defining variables in "where" block would restrict their visibility to
one expression
- it's more easy to read sources when you know which part you can skip,
compare to
def f(x): #do something res = [ f(i) for i in objects ]
in this case you read definition of "f" before you know something about
it usage. 47 3394
Andrey Tatarinov wrote: Hi.
It would be great to be able to reverse usage/definition parts in haskell-way with "where" keyword. Since Python 3 would miss lambda, that would be extremly useful for creating readable sources.
Usage could be something like:
>>> res = [ f(i) for i in objects ] where: >>> def f(x): >>> #do something or >>> print words[3], words[5] where: >>> words = input.split() - defining variables in "where" block would restrict their visibility to one expression
How often is this really necessary? Could you describe some benefits of
this? I think the only time I've ever run into scoping problems is with
lambda, e.g.
[lambda x: f(x) for x, f in lst]
instead of
[lambda x, f=f: for x, f in lst]
Are there other situations where you run into these kinds of problems?
- it's more easy to read sources when you know which part you can skip, compare to >>> def f(x): >>> #do something >>> res = [ f(i) for i in objects ]
in this case you read definition of "f" before you know something about it usage.
Hmm... This seems very heavily a matter of personal preference. I find
that your where clause makes me skip the 'res' assignment to read what
the 'res' block contains. I had to read it twice before I actually
looked at the list comprehension. Of course, I'm sure I could be
retrained to read it the right way, but until I see some real benefit
from it, I'd rather not have to.
TOOWTDI-ily-yrs,
Steve
Steven Bethard wrote: How often is this really necessary? Could you describe some benefits of this? I think the only time I've ever run into scoping problems is with lambda, e.g.
[lambda x: f(x) for x, f in lst]
instead of
[lambda x, f=f: for x, f in lst]
Sorry, bad example, this should have looked something more like:
[lambda y: f(x, y) for x, f in lst]
....
[lambda y, x=x, f=f: f(x, y) for x, f in lst]
where you actually need the lambda.
Steve
In article <xd********************@comcast.com>,
Steven Bethard <st************@gmail.com> wrote: Andrey Tatarinov wrote: It would be great to be able to reverse usage/definition parts in haskell-way with "where" keyword. Since Python 3 would miss lambda, that would be extremly useful for creating readable sources.
Usage could be something like:
>>> res = [ f(i) for i in objects ] where: >>> def f(x): >>> #do something
or
>>> print words[3], words[5] where: >>> words = input.split()
- defining variables in "where" block would restrict their visibility to one expression
How often is this really necessary? Could you describe some benefits of this? I think the only time I've ever run into scoping problems is with lambda, e.g.
[lambda x: f(x) for x, f in lst]
instead of
[lambda x, f=f: for x, f in lst]
Are there other situations where you run into these kinds of problems?
Note that he says "would be extremely useful for creating readable
sources", so the "these kinds of problems" he would have been thinking
of would be where source was not as readable as it could be. You seem
to be concerned about something else.
I don't by any means agree that this notation is worth adopting, and
in general I think this kind of readability issue is more or less a lost
cause for a language with Python's scoping rules, but the motive makes
sense to me. One way to look at it might be, if I observe that "words"
is assigned to in a where clause, then I know it will not be used
elsewhere in the surrounding scope so I can forget about it right away.
If the name does occur elsewhere, it evidently refers to something else.
Donn Cave, do**@u.washington.edu
Andrey Tatarinov wrote: Hi.
It would be great to be able to reverse usage/definition parts in haskell-way with "where" keyword. Since Python 3 would miss lambda, that would be extremly useful for creating readable sources.
Usage could be something like:
>>> res = [ f(i) for i in objects ] where: >>> def f(x): >>> #do something
I don't know haskell, but it looks SQL-ish to me (only by loose
association). And it's not that unpythonic - it resembles
res = [x for x in sequence if x.isOk()]
or
>>> print words[3], words[5] where: >>> words = input.split()
Here's a shorter version:
print input.split()[3:5:2]
(Does it qualify as obfuscated Python code? :) )
- defining variables in "where" block would restrict their visibility to one expression
- it's more easy to read sources when you know which part you can skip,
Yes, I like the readability of it, too.
compare to >>> def f(x): >>> #do something >>> res = [ f(i) for i in objects ]
in this case you read definition of "f" before you know something about it usage.
When I first read your post, I thought "Well, just one more of those
Py3k ideas that appear on c.l.py every day." But as I look at the latter
example, I think you have just scratched my itch. The same thing has
bugged me more than once in my code.
I think this idea is of the same kind as the @decorator syntax. Guido
moved an operation to a point in the code where it was more visible. You
moved an operation to a more local context where (pun not intended) it
really belongs.
I'm usually rather conservative about Python syntax (@decorators,
absolute/relative imports, if-else operator), but this one could appear
in Python tomorrow and that would be too far in the future for me ;)
Cheers,
AdSR
Donn Cave <do**@u.washington.edu> writes: I don't by any means agree that this notation is worth adopting, and in general I think this kind of readability issue is more or less a lost cause for a language with Python's scoping rules, but the motive makes sense to me.
But we're talking about the mythical/hypothetical Python 3, so maybe
there's a chance of fixing the scoping rules, which it seems to me are
currently pretty badly broken.
Andrey Tatarinov wrote: Hi.
It would be great to be able to reverse usage/definition parts in haskell-way with "where" keyword. Since Python 3 would miss lambda, that would be extremly useful for creating readable sources.
Usage could be something like:
>>> res = [ f(i) for i in objects ] where: >>> def f(x): >>> #do something
Hmm, this is actually a really interesting idea. Avoiding accidental namespace
conflicts is certainly one of the advantages of using lambdas.
This idea has the virtue of being able to do the same thing, but have full
access to Python's function syntax and assignment statements in the 'expression
local' suite.
In fact, any subexpressions in a complicated expression can be extracted and
named for clarity without fear of screwing up the containing namespace, which
would be an enormous boon for software maintainers.
It also allows the necessary but uninteresting setup for an expression to be
moved "out of the way", bringing the expression that does the real work to
prominence.
From the interpreter's point of view, the meaning would probably be something like:
namespace = locals()
exec where_suite in globals(), namespace
exec statement in globals(), namespace
res = namespace["res"]
del namespace
Making the 'where' clause part of the grammar for the assignment statement
should be enough to make the above example parseable, too.
The clause might actually make sense for all of the simple statement forms in
the grammar which contain an expression:
expression statement
assignment statement
augmented assignment statement
del statement
print statement
return statement
yield statement
raise statement
exec statement
The clause really isn't appropriate for break, continue, import or global
statements, as they don't contain any expressions :)
For compound statements, a where clause probably isn't appropriate, as it would
be rather unclear what the where clause applied to.
Cheers,
Nick.
--
Nick Coghlan | nc******@email.com | Brisbane, Australia
--------------------------------------------------------------- http://boredomandlaziness.skystorm.net
Nick Coghlan <nc******@iinet.net.au> writes: Usage could be something like: >>> res = [ f(i) for i in objects ] where: >>> def f(x): >>> #do something Hmm, this is actually a really interesting idea. Avoiding accidental namespace conflicts is certainly one of the advantages of using lambdas.
I like it too. Seems a little perl-ish, but what the hey.
In fact, any subexpressions in a complicated expression can be extracted and named for clarity without fear of screwing up the containing namespace, which would be an enormous boon for software maintainers.
Sure, why not:
x = (-b + sqrt(discriminant))/(2*a) where:
discriminant = b*b - 4*a*c
Maybe you could just have a where: suite that binds variables
within the suite:
where:
def f(x):
#do something
res = [ f(i) for i in objects ]
where:
discriminant = b*b - 4*a*c
x = (-b + sqrt(discriminant))/(2*a)
Syntax is
where:
suite
statement
the suite has its own scope so any variable created there is local to
the suite plus the following statement. The scope vanishes after the
statement.
Nick Coghlan wrote: It also allows the necessary but uninteresting setup for an expression to be moved "out of the way", bringing the expression that does the real work to prominence.
Killer app for this keyword:
class C(object):
x = property(get, set) where:
def get(self):
return "Silly property"
def set(self, val):
self.x = "Told you it was silly"
Cheers,
Nick.
--
Nick Coghlan | nc******@email.com | Brisbane, Australia
--------------------------------------------------------------- http://boredomandlaziness.skystorm.net
Paul Rubin wrote: the suite has its own scope so any variable created there is local to the suite plus the following statement. The scope vanishes after the statement.
The second part of the idea is to give the statement greater prominence and
'hide' the uninteresting setup (the contents of the where clause).
Putting the statement of interest after the where suite still gives the benefits
of avoiding namespace clutter, but doesn't really help readability (it makes it
worse, if you ask me).
Particularly, what if the next statement is a compound statement?
Cheers,
Nick.
--
Nick Coghlan | nc******@email.com | Brisbane, Australia
--------------------------------------------------------------- http://boredomandlaziness.skystorm.net But we're talking about the mythical/hypothetical Python 3, so maybe there's a chance of fixing the scoping rules, which it seems to me
are currently pretty badly broken.
I don't think the current scoping rules will be changed in Python 3.0.
I can't give you the link right now, but there are threads about the
scope rules in
python-dev, with various people protesting and Guido saying that he
wants to
keep them as they are.
Michele Simionato
Nick Coghlan wrote: Andrey Tatarinov wrote: Hi.
It would be great to be able to reverse usage/definition parts in haskell-way with "where" keyword. Since Python 3 would miss lambda,
that would be extremly useful for creating readable sources.
Usage could be something like:
>>> res = [ f(i) for i in objects ] where: >>> def f(x): >>> #do something
[snip] For compound statements, a where clause probably isn't appropriate,
as it would be rather unclear what the where clause applied to.
Right. But you know that as soon as you add this to simple
expressions, a bunch of people are going to come here whining about how
they don't get to use where with if-expressions.
Frankly, they might have a point here. Although we have replacing
lambda expressions on our minds, I have in mind a different problem
that a where-statement would solve perfectly. But it would have to be
used with an if-expression.
However, I think it might not be so hard. Let's take Paul Rubin's
advice and precede the if statement with where. Let's also allow
"elif" clauses to be replaced with "else where ... if" clauses. That
which is bound in the while-block would be visible in both the
if-expression and if-block.
Then we could do this:
.. where:
.. m = someregexp.match(somestring)
.. if m:
.. blah blah blah
.. else where:
.. m = someotherregexp.match(somestring)
.. if m:
.. blah blah blah
We might want to spell "else where" instead as "elwhere", to match
"elif", but that's not important now. This would take away one of the
major minor annoyances of Python. (In fact, I've suggested something
like this as a solution to the set-and-test idiom, which Python makes
difficult, only I used the keyword "suppose" instead of "where".)
Ok, but if you do that, now you have people whining that "where" comes
after some expressions, and before others. (This would not bother me
one bit, BTW, but I'm pretty sure I'd lose the popular vote on this
one.)
So, let's go all out and say that while could precede any statement.
We now have consistency. Well, that really wouldn't work for the
if-statement, though, because then how could we apply a different
while-block to an else clause? We'd have to treat if-statements
specially anyways. So we don't have consistency.
My solution would be to propose two different where statements: a
where...do statement, and a separate where...if statement. The
where...do statement would look like this:
.. where:
.. def whatever(): pass
.. do:
.. blah blah use whatever blah
It has the advantage of being able to apply the where bindings to
several statements, and is, IMO, much cleaner looking than simply
applying where's bindings to the single following unindented statement.
I would recommend against where...while and where...for statements.
They can't accomplish anything you couldn't do with a break statement
inside the block, and it's not obvious whether the where clause gets
executed once or for each loop (since it's physically outside the loop
part).
One question: what do you do with a variable bound inside a while-block
that has the same name as a local variable? (Or, horrors, a
surrounding while-block?) I'm inclined to think it should be illegal,
but maybe it would be too restrictive.
Anyways, I like this idea a lot.
+1
--
CARL BANKS
Carl Banks wrote: Right. But you know that as soon as you add this to simple expressions, a bunch of people are going to come here whining about how they don't get to use where with if-expressions.
Frankly, they might have a point here. Although we have replacing lambda expressions on our minds, I have in mind a different problem that a where-statement would solve perfectly. But it would have to be used with an if-expression.
I have a different suggestion for this.
'as' is used for renaming in import statements. 'as' will be used for exception
naming in Python 3k.
So let's use it for expression naming in 'if' statements, too.
if someregexp.match(s) as m:
# blah using m
elif someotherregexp.match(s) as m:
# blah using m
Cheers,
Nick.
--
Nick Coghlan | nc******@email.com | Brisbane, Australia
--------------------------------------------------------------- http://boredomandlaziness.skystorm.net
Nick Coghlan <nc******@iinet.net.au> writes: So let's use it for expression naming in 'if' statements, too.
if someregexp.match(s) as m: # blah using m elif someotherregexp.match(s) as m: # blah using m
Certainly an improvement over what we have now.
Nick Coghlan wrote: Killer app for this keyword:
class C(object):
x = property(get, set) where: def get(self): return "Silly property" def set(self, val): self.x = "Told you it was silly"
Hey, this is super-elegant!
AdSR
AdSR <ad**@poczta.onet.pl> writes: Killer app for this keyword: class C(object): x = property(get, set) where: def get(self): return "Silly property" def set(self, val): self.x = "Told you it was silly"
Hey, this is super-elegant!
Heh, even further:
z = C() where:
class C(object):
...
Lets you make anonymous classes and singleton objects.
On Sat, 08 Jan 2005 16:42:16 +1000, Nick Coghlan <nc******@iinet.net.au> wrote: Nick Coghlan wrote: It also allows the necessary but uninteresting setup for an expression to be moved "out of the way", bringing the expression that does the real work to prominence.
Killer app for this keyword:
class C(object):
x = property(get, set) where: def get(self): return "Silly property" def set(self, val): self.x = "Told you it was silly"
Yes, that is cool and it _is_ an interesting idea. Are suites nestable? E.g., is this legal?
x = term1 + term2 where:
term1 = a*b where:
a = 123
b = 456
term2 = math.pi
Reminds me of some kind of weird let ;-)
And, is the whole thing after the '=' an expression? E.g.,
x = ( foo(x) where:
x = math.pi/4.0
) where:
def foo(x): print 'just for illustration', x
or is this legal?
for y in ([foo(x) for x in bar] where:
bar = xrange(5)
): baz(y) where:
def baz(arg): return arg*2
Not trying to sabotage the idea, really, just looking for clarification ;-)
Regards,
Bengt Richter
Bengt Richter wrote: It also allows the necessary but uninteresting setup for an expression to be moved "out of the way", bringing the expression that does the real work to prominence.Killer app for this keyword:
class C(object):
x = property(get, set) where: def get(self): return "Silly property" def set(self, val): self.x = "Told you it was silly" Yes, that is cool and it _is_ an interesting idea. Are suites nestable? E.g., is this legal?
.... And, is the whole thing after the '=' an expression? E.g.,
x = ( foo(x) where: x = math.pi/4.0 ) where: def foo(x): print 'just for illustration', x
or is this legal?
for y in ([foo(x) for x in bar] where: bar = xrange(5) ): baz(y) where: def baz(arg): return arg*2
Not trying to sabotage the idea, really, just looking for clarification ;-)
yes, all your examples are correct. And that's the way I'd like to use
this feature.
Nick Coghlan wrote: It also allows the necessary but uninteresting setup for an expression to be moved "out of the way", bringing the expression that does the real work to prominence. Killer app for this keyword:
class C(object):
x = property(get, set) where: def get(self): return "Silly property" def set(self, val): self.x = "Told you it was silly"
oh, that's great! I can't imagine prettier example
At the risk of generating controversy, here's another type of example:
def gcd(a, b):
where:
a: int, b: int
return c where:
c: int
while a:
a, b = b%a, a
return b
More can be found at http://aroberge.blogspot.com
Andre
Darn space-eater google groups :-( Here is it again, at teh risk of
generating controversy
..def gcd(a, b):
.. where:
.. a: int, b: int
.. return c where:
.. c: int
.. while a:
.. a, b = b%a, a
.. return b
more examples can be found at aroberge.blogspot.com
André
When I first saw this I thought: "hmmm... this seems as redundant as
adding a repeat/until loop to Python; there's no chance in hell it will
ever be accepted by the community or Guido, but I actually kinda like
it". It's nice to see mostly positive reactions to this idea so far.
I think it's a really ingenious solution to the the anonymous function
problem - don't make it anonymous! A short, throwaway name with a very
localized scope is as good as a truly anonymous function and feels more
Pythonic to me. We thought we wanted a better syntax than lambda for
anonymous functions but Andrey shows that perhaps it wasn't what we
really need. What we need is a solution to quickly and cleanly generate
bits of callable code without polluting the containing namespace,
without having to think too hard about unique names and while making
their temporary and local nature clear from the context. Anonymity
isn't one of the requirements.
I really liked Nick Coghlan's property example. The names 'get' and
'set' are too short and generic to be used without a proper scope but
with this syntax they are just perfect.
Here's another example:
w = Widget(color=Red, onClick=onClick, onMouseOver=onMouseOver) where:
.. def onClick(event): do_this(event.x, event.y, foo)
.. def onMouseOver(event): someotherwidget.do_that()
The "onClick=onClick" part seems a bit redundant, right? So how about
this:
w = Widget(**kw) where:
.. color = Red
.. def onClick(event): do_this(event.x, event.y, blabla)
.. def onMouseOver(event): someotherwidget.do_that()
.. x, y = 100, 200
.. kw = locals()
I'm not really sure myself how much I like this. It has a certain charm
but also feels like abuse of the feature. Note that "w =
Widget(**locals()) where:" would produce the wrong result as it will
include all the values in the containing scope, not just those defined
in the where block.
Oren
Andrey Tatarinov wrote: >>> print words[3], words[5] where: >>> words = input.split()
- defining variables in "where" block would restrict their visibility to one expression
Then your example above doesn't work... print takes a
sequence of expressions, not a tuple as you seem to think.
-Peter
On Sat, 08 Jan 2005 12:53:05 -0500, Peter Hansen <pe***@engcorp.com> wrote: Andrey Tatarinov wrote: >>> print words[3], words[5] where: >>> words = input.split()
- defining variables in "where" block would restrict their visibility to one expression
Then your example above doesn't work... print takes a sequence of expressions, not a tuple as you seem to think.
I found it strange that he had chosen to make the example with
"print", that is a statement. I'm not sure how could it be made to
work with both expressions and statements, it just seems strange...
Overall, I found the idea interesting. It seems like a obvious
counterpart to "with", in the sense that both act as modifiers to the
scoping rules. I think it can be made to work, and that it would lead
to elegant & readable code, but there are still lots of things to
consider: exception handling, fast name lookup in the "where" block,
access to symbols outside the "where" block, just to name a few.
--
Carlos Ribeiro
Consultoria em Projetos
blog: http://rascunhosrotos.blogspot.com
blog: http://pythonnotes.blogspot.com
mail: ca********@gmail.com
mail: ca********@yahoo.com
Peter Hansen wrote: Andrey Tatarinov wrote: >>> print words[3], words[5] where: >>> words = input.split()
- defining variables in "where" block would restrict their
visibility to one expression
Then your example above doesn't work... print takes a sequence of expressions, not a tuple as you seem to think.
You misunderstand. There "where" is not part of the expression but the
statement. The above example would be a modified print statement, a
print...where statement, if you will. Under this suggestion, there
would be modified versions of various simple statements.
This wouldn't be a problem parsing, of course, because "where" would be
a keyword.
--
CARL BANKS
"Carl Banks" <in**********@aerojockey.com> writes: You misunderstand. There "where" is not part of the expression but the statement. The above example would be a modified print statement, a print...where statement, if you will. Under this suggestion, there would be modified versions of various simple statements.
You mean I can't say
# compute sqrt(2) + sqrt(3)
x = (sqrt(a) where:
a = 2.) \
+ sqrt (a) where:
a = 3.
Hmmm.
Bengt Richter wrote: And, is the whole thing after the '=' an expression? E.g.,
x = ( foo(x) where: x = math.pi/4.0 ) where: def foo(x): print 'just for illustration', x
How would that be any improvement over this?
.. x = foo(x) where:
.. x = math.pi/4.0
.. def foo(x): print 'just for illustration', x
Can anyone think of a use case for embedding "where" inside an
expression as opposed to making it part of a simple statement? And, if
so, is the benefit of it worth the massive hit in readability.
or is this legal?
for y in ([foo(x) for x in bar] where: bar = xrange(5) ): baz(y) where: def baz(arg): return arg*2
Here, I can only hope not. One reason I proposed a where...do syntax
is so that, if you wanted to localize a variable to a for loop or some
other compound statement, you could do it with a minimum of fuss.
.. where:
.. bar = xrange(5)
.. def baz(arg): return arg*2
.. do:
.. for y in [foo(x) for x in bar]:
.. baz(y)
Not trying to sabotage the idea, really, just looking for
clarification ;-)
That's ok. For it fly, it's got to be able to withstand the flak.
--
CARL BANKS
Paul Rubin wrote: "Carl Banks" <in**********@aerojockey.com> writes: You misunderstand.
BTW, Peter, I guess I should have said "I misunderstand, but it can be
legal if you consider it part of the statements", since it appears the
author did intend it to be part of an expression.
There "where" is not part of the expression but the statement. The above example would be a modified print statement,
a print...where statement, if you will. Under this suggestion, there would be modified versions of various simple statements.
You mean I can't say
# compute sqrt(2) + sqrt(3) x = (sqrt(a) where: a = 2.) \ + sqrt (a) where: a = 3.
Hmmm.
What would be the advantage of that over this?
.. x = sqrt(a) + sqrt(b) where:
.. a = 2.0
.. b = 3.0
Where would making "where" part of an expression rather than part of
the statement help? Can you think of a place? ("That it makes Python
more like LISP" is not a good enough answer for me, BTW. But feel free
to try. :)
--
CARL BANKS
"Carl Banks" <in**********@aerojockey.com> writes: # compute sqrt(2) + sqrt(3) x = (sqrt(a) where: a = 2.) \ + sqrt (a) where: a = 3.
Hmmm.
What would be the advantage of that over this?
. x = sqrt(a) + sqrt(b) where: . a = 2.0 . b = 3.0
The idea of "where" is to allow re-using variable names instead of
having to keep track of which ones are in use. I just tried to give a
very simple example of how you might do that more than once in a
statement.
Nick Coghlan wrote: I have a different suggestion for this.
'as' is used for renaming in import statements. 'as' will be used for
exception naming in Python 3k.
So let's use it for expression naming in 'if' statements, too.
if someregexp.match(s) as m: # blah using m elif someotherregexp.match(s) as m: # blah using m
What if the condition you wanted to test wasn't the same as the thing
you want to save? In other words, how would you convert this?
.. where:
.. m = something()
.. if m > 20:
.. do_something_with(m)
What you propose works for typical regexps idiom but not for the
slightly more general case. However, I could see why some people might
not like the where...if syntax I proposed; it's kind of choppy and not
exactly easy to follow at a first glance.
As a compromise, howabout :
.. if m > 20 where m=something():
.. do_something_with(m)
In this case, the m=something() is NOT an assignment statement, but
merely a syntax resembling it. The "where m=something()" is part of
the if-statement, not the if-expression. It causes m to be visisble in
the if-expression and the if-block.
It (or your suggestion) could work with a while-loop too.
.. while line where line=f.readline():
.. do_something_with(line)
The main problem here (as some would see it) is that you can't do
something this:
.. if m > 20 where (def m(): a(); b()):
--
CARL BANKS
Paul Rubin wrote: "Carl Banks" <in**********@aerojockey.com> writes:
When I asked you to do this, it was just a rhetorical way to tell you that I didn't intend to play this game. It's plain as day you're trying to get me to admit something. I'm not falling for it.
If you have a point to make, why don't you just make it?
You asked me to compare the notion of macros with the Zen list. I did so. I didn't see any serious conflict, and reported that finding. Now you've changed your mind and you say you didn't really want me to make that comparison after all.
Well I for one disagreed with many of your estimates of the zen's
applicability to macros, but I just couldn't be arsed saying so.
An amazing amount of the headaches that both newbies and experienced users have with Python, could be solved by macros. That's why there's been an active interest in macros for quite a while. It's not clear what the best way to do design them is, but their existence can have a profound effect on how best to do these ad-hoc syntax extensions like "where". Arbitrary limitations that are fairly harmless without macros become a more serious pain in the neck if we have macros.
This is not a justifiable assertion, IMHO, and if you think that newbies
will have their lives made easier by the addition of ad hoc syntax
extensions then you and I come from a different world (and I suspect the
walls might be considerably harder in mine than in yours).
So, we shouldn't consider these topics separately from each other. They are likely to end up being deeply related.
I don't really understand why, if macros are so great (and you are
reading the words of one who was using macros back in the days of
Strachey's GPM) why somebody doesn't produce a really useful set of
(say) M4 macros to prove how much they'd improve Python.
Now that's something that would be a bit less ignorable than this
apparently interminable thread.
regards
Steve
PS: Your continued use of the NOSPAM.invalid domain is becoming much
more irritating than your opinions on macros in Python. Using a bogus
URL is piling crap on top of more crap.
--
Steve Holden http://www.holdenweb.com/
Python Web Programming http://pydish.holdenweb.com/
Holden Web LLC +1 703 861 4237 +1 800 494 3119
Steve Holden <st***@holdenweb.com> writes: Well I for one disagreed with many of your estimates of the zen's applicability to macros, but I just couldn't be arsed saying so.
Well, I was being somewhat flip with them, as I felt Carl was being
snotty in referring me to the Zen list. The point there is that one
can interpret each of the Zen points in many ways regarding macros. I
don't feel there's a conflict between macros and the Zen list. Macros
in Python are a deep subject and gurus have been discussing them for a
long time. I think that with PyPy it will become easier to experiment
with possible approaches. In other posts I've suggested a moratorium
on new Python syntax until after PyPy is deployed. An amazing amount of the headaches that both newbies and experienced users have with Python, could be solved by macros.... It's not clear what the best way to do design them is, but their existence can have a profound effect on how best to do these ad-hoc syntax extensions like "where". This is not a justifiable assertion, IMHO, and if you think that newbies will have their lives made easier by the addition of ad hoc syntax extensions then you and I come from a different world (and I suspect the walls might be considerably harder in mine than in yours).
I'm saying that many proposals for ad hoc extensions could instead be
taken care of with macros. Newbies come to clpy all the time asking
how to do assignment expressions, or conditional expressions, or
call-by-reference. Sometimes new syntax results. Lots of times,
macros could take care of it.
I don't really understand why, if macros are so great (and you are reading the words of one who was using macros back in the days of Strachey's GPM) why somebody doesn't produce a really useful set of (say) M4 macros to prove how much they'd improve Python.
You can't really do Python macros with something like M4. How would
M4 even generate multi-line output that's indented to the right depth
for the place where the macro was called? How would you write an
m4 macro like cond(x,y,z) that does the equivalent of (x ? y : z)?
Even if you could, it doesn't begin to address the hassle of running
Python scripts through m4 before you can execute the scripts, especially
in an interactive environment.
Nick Coghlan wrote: Semantics --------- The code::
<statement> with: <suite>
translates to::
def unique_name(): <suite> <statement> unique_name()
Bleh. Not only was my proposed grammar change wrong, my suggested semantics are
wrong, too.
Raise your hand if you can see the problem with applying the above semantics to
the property descriptor example.
So I think the semantics will need to be more along the lines of "pollute the
namespace but mangle the names so they're unique, and the programmer can *act*
like the names are statement local".
This will be much nicer in terms of run-time performance, but getting the
locals() builtin to behave sensibly may be a challenge.
Cheers,
Nick.
--
Nick Coghlan | nc******@email.com | Brisbane, Australia
--------------------------------------------------------------- http://boredomandlaziness.skystorm.net
Nick Coghlan wrote: Semantics --------- The code::
<statement> with: <suite>
translates to::
def unique_name(): <suite> <statement> unique_name()
Bleh. Not only was my proposed grammar change wrong, my suggested semantics are wrong, too.
Raise your hand if you can see the problem with applying the above semantics to the property descriptor example.
So I think the semantics will need to be more along the lines of "pollute the namespace but mangle the names so they're unique, and the programmer can *act* like the names are statement local".
This will be much nicer in terms of run-time performance, but getting the locals() builtin to behave sensibly may be a challenge.
afair you told yourself that
var = <statement> where:
<suite>
translates to:
def unique_name():
<suite>
return <statement>
var = unique_name()
in this case class gets unique_name() function? is it that bad?
anyway I'd prefer to change semantics deeper. adding new statement-only
scope and adding our suite-definitions there.
Nick Coghlan wrote: Nick Coghlan wrote:
Semantics --------- The code::
<statement> with: <suite>
translates to::
def unique_name(): <suite> <statement> unique_name()
Bleh. Not only was my proposed grammar change wrong, my suggested semantics are wrong, too.
Raise your hand if you can see the problem with applying the above semantics to the property descriptor example.
Eh, never mind. The following works today, so the semantics I proposed are
actually fine. (This is exactly the semantics proposed for the property example)
Py> class C(object):
.... def _x():
.... def get(self):
.... print "Hi!"
.... def set(self, value):
.... print "Hi again!"
.... def delete(self):
.... print "Bye"
.... return property(get, set, delete)
.... x = _x()
....
Py> C.x
<property object at 0x009E6738>
Py> C().x
Hi!
Py> C().x = 1
Hi again!
Py> del C().x
Bye
Cheers,
Nick.
--
Nick Coghlan | nc******@email.com | Brisbane, Australia
--------------------------------------------------------------- http://boredomandlaziness.skystorm.net
Andrey Tatarinov wrote: afair you told yourself that
var = <statement> where: <suite>
translates to:
def unique_name(): <suite> return <statement> var = unique_name()
in this case class gets unique_name() function? is it that bad?
No, I wasn't thinking clearly and saw problems that weren't there.
However, you're right that the semantic definition should include unbinding the
unique name after the statement finishes. E.g. for assignments:
def unique_name():
<suite>
return <expr>
<target> = unique_name()
del unique_name
anyway I'd prefer to change semantics deeper. adding new statement-only scope and adding our suite-definitions there.
A new scope essentially *is* a nested function :)
My main purpose with the nested function equivalent is just to make the intended
semantics clear - whether an implementation actually _does_ things that way is
immaterial.
Cheers,
Nick.
--
Nick Coghlan | nc******@email.com | Brisbane, Australia
--------------------------------------------------------------- http://boredomandlaziness.skystorm.net
Andrey Tatarinov wrote: I think using 'with' keyword can cause some ambiguity. for example I would surely try to write
>>> x = a+b with self: >>> b = member and using with at the end of block brings more ambiguity: >>> stmt1() >>> stmt2() >>> with self: >>> member = stmt3() compare to: >>> stmt1() >>> stmt2() >>> with: >>> variable = stmt3()
a way different semantics with just one word added/deleted.
Except that for a "with <expr>:" block, attributes of the expression must be
preceded by a dot:
Py> stmt1()
Py> stmt2()
Py> with self:
.... .member = stmt3()
The advantages of the 'with' block are that 'self' is only looked up once, and
you only need to type it once. The leading dot is still required to disambiguate
attribute references from standard name references.
Despite that, I think you are right that the ambiguity is greater than I first
thought. Correct code is reasonably easy to distinguish, but in the presence of
errors it is likely to be unclear what was intended, which would make life more
difficult than it needs to be.
However, I still agree with Alex that the dual life of "where" outside of Python
(as an 'additional definitions' clause, as in mathematics, and as a
'conditional' clause, as in SQL), and the varied background of budding
Pythoneers is a cause for concern.
'in' is worth considering, as it is already used by Python at least once for
declaring use of a namespace (in the 'exec' statement). However, I suspect it
would suffer from ambiguity problems similar to those of 'with' (consider
"<expr> in <expr>" and "<expr> in: <expr>"). There's also the fact that the
statement isn't *really* executed in the inner namespace - any name binding
effects are seen in the outer scope, whereas 'exec x in dict' explicitly
protects the containing namespace from alteration.
So of the four keywords suggested so far ('where', 'with', 'in', 'using'), I'd
currently vote for 'using' with 'where' a fairly close second. My vote goes to
'using' because it has a fairly clear meaning ('execute the statement using this
extra information'), and doesn't have the conflicting external baggage that
'where' does.
Cheers,
Nick.
--
Nick Coghlan | nc******@email.com | Brisbane, Australia
--------------------------------------------------------------- http://boredomandlaziness.skystorm.net
> So of the four keywords suggested so far ('where', 'with', 'in', 'using'), I'd currently vote for 'using' with 'where' a fairly close second. My vote goes to 'using' because it has a fairly clear meaning ('execute the statement using this extra information'), and doesn't have the conflicting external baggage that 'where' does.
I should agree with you =)
Though I love "with" for historical reasons and addiction to functional
languages "using" is not that bad and I do not mind using it. =)
Paul Rubin wrote: Steve Holden <st***@holdenweb.com> writes:
[...] and if you think that newbies will have their lives made easier by the addition of ad hoc syntax extensions then you and I come from a different world (and I suspect the walls might be considerably harder in mine than in yours).
I'm saying that many proposals for ad hoc extensions could instead be taken care of with macros. Newbies come to clpy all the time asking how to do assignment expressions, or conditional expressions, or call-by-reference. Sometimes new syntax results. Lots of times, macros could take care of it.
Personally, given the requests in question, I'm extremely thankful
that I don't have to worry about reading Python code that uses them.
I don't *want* people to be able to make up their own
control-structure syntax, because that means I need to be able to
decipher the code of someone who wants to write Visual Basic as
filtered through Java and Perl... If I want mental gymnastics when
reading code, I'd use Lisp (or Forth). (These are both great
languages, and mental gymnastics would probably do me good, but I
wouldn't want it as part of my day-to-day requirements...)
Jeff Shannon
Technician/Programmer
Credit International
Op 2005-01-11, Jeff Shannon schreef <je**@ccvcorp.com>: Paul Rubin wrote:
Steve Holden <st***@holdenweb.com> writes:
[...] and if you think that newbies will have their lives made easier by the addition of ad hoc syntax extensions then you and I come from a different world (and I suspect the walls might be considerably harder in mine than in yours). I'm saying that many proposals for ad hoc extensions could instead be taken care of with macros. Newbies come to clpy all the time asking how to do assignment expressions, or conditional expressions, or call-by-reference. Sometimes new syntax results. Lots of times, macros could take care of it.
Personally, given the requests in question, I'm extremely thankful that I don't have to worry about reading Python code that uses them. I don't *want* people to be able to make up their own control-structure syntax, because that means I need to be able to decipher the code of someone who wants to write Visual Basic as filtered through Java and Perl...
No you don't.
You could just as well claim that you don't want people to write
code in other languages because you then would need to be able
to decipher code written in that language.
If I want mental gymnastics when reading code, I'd use Lisp (or Forth). (These are both great languages, and mental gymnastics would probably do me good, but I wouldn't want it as part of my day-to-day requirements...)
Your day-to-day requirements are a contract between you and your
employer or between you and your clients. That you don't want
mental gymnastics as part of that, shouldn't be a concern for
how the language develops.
--
Antoon Pardon
Nick Coghlan wrote: Semantics --------- The code::
<statement> with: <suite>
translates to::
def unique_name(): <suite> <statement> unique_name()
I've come to the conclusion that these semantics aren't what I would expect from
the construct. Exactly what I would expect can't really be expressed in current
Python due to the way local name bindings work. The main thing to consider is
what one would expect the following to print:
def f():
a = 1
b = 2
print 1, locals()
print 3, locals() using:
a = 2
c = 3
print 2, locals()
print 4, locals()
I think the least suprising result would be:
1 {'a': 1, 'b': 2} # Outer scope
2 {'a': 2, 'c': 3} # Inner scope
3 {'a': 2, 'b': 2, 'c': 3} # Bridging scope
4 {'a': 1, 'b': 2} # Outer scope
In that arrangement, the statement with a using clause is executed normally in
the outer scope, but with the ability to see additional names in its local
namespace. If this can be arranged, then name binding in the statement with the
using clause will work as we want it to.
Anyway, I think further investigation of the idea is dependent on a closer look
at the feasibility of actually implementing it. Given that it isn't as
compatible with the existing nested scope structure as I first thought, I
suspect it will be both tricky to implement, and hard to sell to the BDFL
afterwards :(
Cheers,
Nick.
--
Nick Coghlan | nc******@email.com | Brisbane, Australia
--------------------------------------------------------------- http://boredomandlaziness.skystorm.net
Nick Coghlan wrote: def f(): a = 1 b = 2 print 1, locals() print 3, locals() using: a = 2 c = 3 print 2, locals() print 4, locals()
I think the least suprising result would be:
1 {'a': 1, 'b': 2} # Outer scope 2 {'a': 2, 'c': 3} # Inner scope 3 {'a': 2, 'b': 2, 'c': 3} # Bridging scope 4 {'a': 1, 'b': 2} # Outer scope
Personally, I think that the fact that the bridging statement is
executed *after* the inner code block guarantees that results will be
surprising. The fact that it effectively introduces *two* new scopes
just makes matters worse.
It also seems to me that one could do this using a nested function def
with about the same results. You wouldn't have a bridging scope with
both sets of names as locals, but your nested function would have
access to the outer namespace via normal nested scopes, so I'm really
not seeing what the gain is...
(Then again, I haven't been following the whole using/where thread,
because I don't have that much free time and the initial postings
failed to convince me that there was any real point...)
Jeff Shannon
Technician/Programmer
Credit International In that arrangement, the statement with a using clause is executed normally in the outer scope, but with the ability to see additional names in its local namespace. If this can be arranged, then name binding in the statement with the using clause will work as we want it to.
Anyway, I think further investigation of the idea is dependent on a closer look at the feasibility of actually implementing it. Given that it isn't as compatible with the existing nested scope structure as I first thought, I suspect it will be both tricky to implement, and hard to sell to the BDFL afterwards :(
Cheers, Nick.
Nick Coghlan wrote: Nick Coghlan wrote:
Semantics --------- The code::
<statement> with: <suite>
translates to::
def unique_name(): <suite> <statement> unique_name() I've come to the conclusion that these semantics aren't what I would expect from the construct. Exactly what I would expect can't really be expressed in current Python due to the way local name bindings work. The main thing to consider is what one would expect the following to print:
def f(): a = 1 b = 2 print 1, locals() print 3, locals() using: a = 2 c = 3 print 2, locals() print 4, locals()
I think the least suprising result would be:
1 {'a': 1, 'b': 2} # Outer scope 2 {'a': 2, 'c': 3} # Inner scope 3 {'a': 2, 'b': 2, 'c': 3} # Bridging scope 4 {'a': 1, 'b': 2} # Outer scope
as for me, I would expect following:
1 {'a': 1, 'b': 2}
2 {'a': 2, 'b': 2, 'c': 3'}
3 {'a': 2, 'b': 2, 'c': 3'}
4 {'a': 1, 'b': 2}
otherwise that would be impossible to do calculations based on scope
variables and "using:" would be useless =), consider example of usage:
current_position = 1
current_environment # = ...
current_a_lot_of_other_parameters # = ...
scores = [count_score(move) for move in aviable_moves] using:
def count_score(move):
#walking through current_environment
return score
On Thu, 13 Jan 2005 22:41:54 +0300, Andrey Tatarinov <el********@dezcom.mephi.ru> wrote: Nick Coghlan wrote: Nick Coghlan wrote:
Semantics --------- The code::
<statement> with: <suite>
translates to::
def unique_name(): <suite> <statement> unique_name() I've come to the conclusion that these semantics aren't what I would expect from the construct. Exactly what I would expect can't really be expressed in current Python due to the way local name bindings work. The main thing to consider is what one would expect the following to print:
def f(): a = 1 b = 2 print 1, locals() print 3, locals() using: a = 2 c = 3 print 2, locals() print 4, locals()
I think the least suprising result would be:
1 {'a': 1, 'b': 2} # Outer scope 2 {'a': 2, 'c': 3} # Inner scope 3 {'a': 2, 'b': 2, 'c': 3} # Bridging scope 4 {'a': 1, 'b': 2} # Outer scope
as for me, I would expect following:
1 {'a': 1, 'b': 2} 2 {'a': 2, 'b': 2, 'c': 3'} 3 {'a': 2, 'b': 2, 'c': 3'} 4 {'a': 1, 'b': 2}
locals() doesn't automatically show everything that is visible from its local scope: def foo():
... a = 1
... b = 2
... print 1, locals()
... def inner():
... a = 2
... c = 3
... print 2, locals()
... inner()
... print 4, locals()
... foo()
1 {'a': 1, 'b': 2}
2 {'a': 2, 'c': 3}
4 {'a': 1, 'b': 2, 'inner': <function inner at 0x02EE8BFC>}
-- unless you actually use it (this is a bit weird maybe?):
def foo():
... a = 1
... b = 2
... print 1, locals()
... def inner():
... a = 2
... c = 3
... print 2, locals(), 'and b:', b
... inner()
... print 4, locals()
... foo()
1 {'a': 1, 'b': 2}
2 {'a': 2, 'c': 3, 'b': 2} and b: 2
4 {'a': 1, 'b': 2, 'inner': <function inner at 0x02EE8D4C>}
of course a difference using the new syntax is that 'inner' is not bound to a persistent name. otherwise that would be impossible to do calculations based on scope variables and "using:" would be useless =), consider example of usage:
current_position = 1 current_environment # = ... current_a_lot_of_other_parameters # = ... scores = [count_score(move) for move in aviable_moves] using: def count_score(move): #walking through current_environment return score
No worry, UIAM.
Regards,
Bengt Richter
On Fri, 14 Jan 2005 01:48:48 +1000, Nick Coghlan <nc******@iinet.net.au> wrote: Nick Coghlan wrote: Semantics --------- The code::
<statement> with: <suite>
translates to::
def unique_name(): <suite> <statement> unique_name()
I've come to the conclusion that these semantics aren't what I would expect from the construct. Exactly what I would expect can't really be expressed in current Python due to the way local name bindings work. The main thing to consider is what one would expect the following to print:
def f(): a = 1 b = 2 print 1, locals() print 3, locals() using: a = 2 c = 3 print 2, locals() print 4, locals()
I think the least suprising result would be:
1 {'a': 1, 'b': 2} # Outer scope 2 {'a': 2, 'c': 3} # Inner scope 3 {'a': 2, 'b': 2, 'c': 3} # Bridging scope 4 {'a': 1, 'b': 2} # Outer scope
In that arrangement, the statement with a using clause is executed normally in the outer scope, but with the ability to see additional names in its local namespace. If this can be arranged, then name binding in the statement with the using clause will work as we want it to.
Anyway, I think further investigation of the idea is dependent on a closer look at the feasibility of actually implementing it. Given that it isn't as compatible with the existing nested scope structure as I first thought, I suspect it will be both tricky to implement, and hard to sell to the BDFL afterwards :(
In the timbot's let/in format:
def f():
a = 1
b = 2
print 1, locals()
let:
a = 2
c = 3
print 2, locals()
in:
print 3, locals()
print 4, locals()
I think the effect would be as if def f():
... a = 1
... b = 2
... print 1, locals()
... def __unique_temp():
... a = 2
... c = 3
... print 2, locals()
... def __unique_too():
... print 3, locals()
... __unique_too()
... __unique_temp()
... del __unique_temp
... print 4, locals()
... f()
1 {'a': 1, 'b': 2}
2 {'a': 2, 'c': 3}
3 {}
4 {'a': 1, 'b': 2}
print 3, locals() doesn't show a,b,c in locals() unless you use them
somehow in that scope, e.g.,
def f():
... a = 1
... b = 2
... print 1, locals()
... def __unique_temp():
... a = 2
... c = 3
... print 2, locals()
... def __unique_too():
... print 3, locals(), (a,b,c) # force references for locals()
... __unique_too()
... __unique_temp()
... del __unique_temp
... print 4, locals()
... f()
1 {'a': 1, 'b': 2}
2 {'a': 2, 'c': 3, 'b': 2}
3 {'a': 2, 'c': 3, 'b': 2} (2, 2, 3)
4 {'a': 1, 'b': 2}
Of course, locals() does not include globals, even though they're
referenced and visible: b
'global b' def bar():
... print locals(), b
... bar()
{} global b
The trouble with this is that bindings created in __unique_too all get thrown away,
and you wouldn't want that limitation. So I proposed specifying the (re)bindable names
in a parenthesized list with the let, like "let(k, q, w): ..." so that those names
would be (re)bindable in the same scope as the let(...): statement.
As an extension, I also proposed optionally binding __unique_temp to a specified name
and not calling it automatically, instead of the automatic call and del.
That provides new ways to factor updates to local namespaces into local functions
with selective write-through (bind/rebind) to local names. E.g.,
# define case blocks for switch
# better sugar later, this is to demo functinality ;-)
#a
let(x):
k = 123
in foo:
x = k
#b
let(x, y):
q = 456
from math import pi as r
in bar:
x = q
y=r # extra binding created if bar is called
#c
let(x):in baz:x=789 # most compact form, where nothing in the let clause
switch = dict(a=foo, b=bar, c=baz)
Now you can update local bindings with a case switch:
x = 0
case = 'b'
print x # => 0
switch[case]() # executes bar() in this example, which assigns local x=456 and y=pi
print x # => 456
This spare example is easy to dismiss, but think of foo, bar, and baz as arbitrary sequences of statements
in the local namespace, except you can factor them out as a single named group and invoke them
safely by name(), and have them affect only the local names you specify in the group's let(x, y, ...): spec.
It provides a new way of factoring. As well as things no one has thought of yet ;-)
The other thing to think about is that the let suite could be strictly def-time, which would
provide the opportunity to avoid re-calculating things in functions without abusing default args,
and using the easy closure-variable creation instead. E.g.,
let(foo):
preset = big_calc()
in:
def foo(x):
return x * preset
(This "in:" has no "in xxx:" name, so the effect is immediate execution of the anonymously
defined function, which writes through to foo with the def, as permitted by let(foo):).
Problems? (Besides NIH, which I struggle with regularly, and had to overcome to accept Tim's
starting point in this ;-)
Regards,
Bengt Richter
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 | nc******@email.com | Brisbane, Australia
--------------------------------------------------------------- http://boredomandlaziness.skystorm.net
Nick Coghlan wrote: 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
The more I think about this return-based approach, the less I like it. It could
probably be made to work, but it just feels like a kludge to work around the
fact that the only mechanisms available for altering the bindings of local names
are assignment and definition statements.
For class namespaces, getattr(), setattr() and delattr() work a treat, and
globals() works fine for module level name binding.
locals() is an unfortunate second class citizen, since it writes to it aren't
propagated back to the executing frame. Programmatic interrogation of locals is
fine, but update is impossible.
What would be interesting is if locals() returned a dictionary whose __setitem__
method invoked PyFrame_LocalsToFast on the relevant frame, instead of a vanilla
dictionary as it does now.
Then locals()["x"] = foo would actually work properly.
Notice that you can get this effect today, by using exec to force invocation of
PyFrame_LocalsToFast:
Py> def f():
.... n = 1
.... def g(outer=locals()):
.... outer["n"] += 1
.... g() # Does not affect n
.... print n
.... exec "g()" # DOES affect n
.... print n
....
Py> f()
1
2
(The call to g() has to be inside the exec statement, since the exec statement
evaluation starts with a call to PyFrame_FastToLocals).
Assuming a writeable locals(), the semantics for the normal case are given by:
============
def __use_stmt(__outer):
<use-suite>
<in-suite>
__inner = locals()
for name in <names>:
__outer[name] = __inner[name]
__use_stmt(locals())
del __use_stmt
============
And for the 'delayed execution' case:
============
def __named_use_stmt(__outer):
<use-suite>
def __delayed_block():
<in-suite>
__inner = locals()
for name in <names>:
__outer[name] = __inner[name]
return __delayed_block
<in-name> = __named_use_stmt(locals())
del __named_use_stmt
============
Cheers,
Nick.
--
Nick Coghlan | nc******@email.com | Brisbane, Australia
--------------------------------------------------------------- http://boredomandlaziness.skystorm.net
Nick Coghlan wrote: # Anonymous functions use res: def f(x): d = {} exec x in d return d in: res = [f(i) for i in executable]
as for me, I found construction "use <name>:" unobvious and confusing.
Also there is great possibility to forget some of variables names.
I think that syntax
<block>
where:
<block>
is more obvious. (and we already have defined semantics for it)
we have two problems, that we try to solve
1) create method to nest scopes
2) create method to reverse execution order for better readability
"using:" solves both at once.
but your "use ... in ..." syntax shows, that you want to be able to
solve 1) independently i.e. create nested scope without reversing
execution order.
so, I can suggest one more keyword "do:", which will create nested
scope, just as "def f(): ... ; f()" do (and that could be just syntaxic
sugar for it.
so "use ... in ..." would look the following way:
do:
res = [f(i) for i in executable]
#some more equations here
using:
def f(x):
d = {}
exec x in d
return d
that seems good for me. of course if you want to return something from
the nest scope you must show that variable is from parent scope.
// while writing that I realized that it's too complex to be implemented
in python in that way. consider it as some type of brainstorming. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: michele.simionato |
last post by:
Paul Rubin wrote:
> How about macros? Some pretty horrible things have been done in C
> programs with the C preprocessor. But there's a movememnt...
|
by: tammygombez |
last post by:
Hey fellow JavaFX developers,
I'm currently working on a project that involves using a ComboBox in JavaFX, and I've run into a bit of an issue....
|
by: tammygombez |
last post by:
Hey everyone!
I've been researching gaming laptops lately, and I must say, they can get pretty expensive. However, I've come across some great...
|
by: teenabhardwaj |
last post by:
How would one discover a valid source for learning news, comfort, and help for engineering designs? Covering through piles of books takes a lot of...
|
by: CD Tom |
last post by:
This happens in runtime 2013 and 2016. When a report is run and then closed a toolbar shows up and the only way to get it to go away is to right...
|
by: CD Tom |
last post by:
This only shows up in access runtime. When a user select a report from my report menu when they close the report they get a menu I've called Add-ins...
|
by: Naresh1 |
last post by:
What is WebLogic Admin Training?
WebLogic Admin Training is a specialized program designed to equip individuals with the skills and knowledge...
|
by: antdb |
last post by:
Ⅰ. Advantage of AntDB: hyper-convergence + streaming processing engine
In the overall architecture, a new "hyper-convergence" concept was...
|
by: Matthew3360 |
last post by:
Hi there. I have been struggling to find out how to use a variable as my location in my header redirect function.
Here is my code.
...
|
by: Matthew3360 |
last post by:
Hi, I have a python app that i want to be able to get variables from a php page on my webserver. My python app is on my computer. How would I make it...
| |