Re: [Python-Dev] Proper place to put extra args for building
Brett C. wrote: Works for me. If no one objects I will check in the change for CFLAGS to make it ``$(BASECFLAGS) $(OPT) $EXTRA_CFLAGS`` soon (is quoting it enough to make sure that it isn't evaluated by configure but left as a string to be evaluated by the shell when the Makefile is running?). If you put it into Makefile.pre.in, the only thing to avoid that configure evaluates is is not to use @[EMAIL PROTECTED] OTOH, putting a $ in front of it is not good enough for make: $EXTRA_CFLAGS evaluates the variable E, and then appends XTRA_CFLAGS. Regards, Martin ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Re: anonymous blocks
On 4/20/05, Samuele Pedroni [EMAIL PROTECTED] wrote: def do(): print setup try: yield None finally: print tear down doesn't quite work (if it did, all you would need is syntactic sugar for for dummy in). PEP325 is about that And, of course, PEP 310 is all about encapsulating before/after (acquire/release) actions. Paul. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Re: switch statement
Shannon -jj Behrens [EMAIL PROTECTED] writes: On 4/20/05, M.-A. Lemburg [EMAIL PROTECTED] wrote: My use case for switch is that of a parser switching on tokens. mxTextTools applications would greatly benefit from being able to branch on tokens quickly. Currently, there's only callbacks, dict-to-method branching or long if-elif-elif-...-elif-else. I think match from Ocaml would be a much nicer addition to Python than switch from C. Can you post a quick summary of how you think this would work? Cheers, mwh -- We did requirements and task analysis, iterative design, and user testing. You'd almost think programming languages were an interface between people and computers.-- Steven Pemberton (one of the designers of Python's direct ancestor ABC) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Re: switch statement
I can post an alternative, inspired by this bit of Haskell (I've deliberately left out the Haskell type annotation for this): zoneOpts argv = case getOpt Permute options argv of (o,n,[]) - return (o,n) (_,_,errs) - error errs which could, in a future Python, look something like: def zoneOpts(argv): case i of getopt(argv, options, longoptions): i[2]: raise OptionError(i[2]) True: return i[:2] The intent is that within the case, the bit before each : is a boolean expression, they're evaluated in order, and the following block is executed for the first one that evaluates to be True. I know we have exceptions for this specific example, but it's just an example. I'm also assuming for the time being that getopt returns a 3-tuple (options, arguments, errors) like the Haskell version does, just for the sake of argument, and there's an OptionError constructor that will do something with that error list.. Yes, that is very different semantics from a Haskell case expression, but it kind of looks like a related idea. A more closely related idea would be to borrow the Haskell patterns: def zoneOpts(argv): case getopt(argv, options, longoptions): (o,n,[]): return o,n (_,_,errs): raise OptionError(errs) where _ matches anything, a presently unbound name is bound for the following block by mentioning it, a bound name would match whatever value it referred to, and a literal matches only itself. The first matching block gets executed. Come to think of it, it should be possible to do both. Not knowing Ocaml, I'd have to presume that 'match' is somewhat similar. Andrew On 21/04/2005, at 9:30 PM, Michael Hudson wrote: Shannon -jj Behrens [EMAIL PROTECTED] writes: On 4/20/05, M.-A. Lemburg [EMAIL PROTECTED] wrote: My use case for switch is that of a parser switching on tokens. mxTextTools applications would greatly benefit from being able to branch on tokens quickly. Currently, there's only callbacks, dict-to-method branching or long if-elif-elif-...-elif-else. I think match from Ocaml would be a much nicer addition to Python than switch from C. Can you post a quick summary of how you think this would work? Cheers, mwh -- We did requirements and task analysis, iterative design, and user testing. You'd almost think programming languages were an interface between people and computers.-- Steven Pemberton (one of the designers of Python's direct ancestor ABC) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/ andrew%40indranet.co.nz ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] Re: Re: anonymous blocks
Josiah Carlson wrote: for my purposes, I've found that the #1 callback killer in contemporary Python is for-in:s support for the iterator protocol: ... and get shorter code that runs faster. (see cElementTree's iterparse for an excellent example. for typical use cases, it's nearly three times faster than pyexpat, which is the fastest callback-based XML parser we have) It seems as though you are saying that because callbacks are so slow, that blocks are a non-starter for you because of how slow it would be to call them. Not really -- I see the for-in loop body as the block. The increased speed is just a bonus. I'm thinking that if people get correct code easier, that speed will not be as much of a concern (that's why I use Python already). (Slightly OT, but speed is always a concern. I no longer buy the it's python, it has to be slow line of reasoning; when done correctly, Python code is often faster than anything else. cElementTree is one such example; people have reported that cElementTree plus Python code can be a lot faster than dedicated XPath/XSLT engines; the Python bytecode engine is extremely fast, also compared to domain-specific interpreters... And in this case, you get improved usability *and* improved speed at the same time. That's the way it should be.) With that said, both blocks and iterators makes /writing/ such things easier to understand, but neither really makes /reading/ much easier. Sure, it is far more terse, but that doesn't mean it is easier to read and understand what is going on. Well, I was talking about reading here: with the for-in pattern, you loop over the callback source, and the callback itself is inlined. You don't have to think in here is the callback, here I configure the callback source terms; just make a function call and loop over the result. Regardless, I believe that solving generator finalization (calling all enclosing finally blocks in the generator) is a worthwhile problem to solve. Whether that be by PEP 325, 288, 325+288, etc., that should be discussed. Whether people use it as a pseudo-block, or decide that blocks are further worthwhile, I suppose we could wait and see. Agreed. /F ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Re: anonymous blocks
On Apr 21, 2005, at 6:28 AM, Fredrik Lundh wrote: Glyph Lefkowitz wrote: Despite being guilty of propagating this style for years myself, I have to disagree. Consider the following network-conversation using Twisted style (which, I might add, would be generalizable to other Twisted-like systems if they existed ;-)): def strawman(self): def sayGoodbye(mingleResult): def goAway(goodbyeResult): self.loseConnection() self.send(goodbye).addCallback(goAway) def mingle(helloResult): self.send(nice weather we're having).addCallback(sayGoodbye) self.send(hello).addCallback(mingle) def iterman(self): yield hello yield nice weather we're having yield goodbye Which, more or less works, for a literal translation of the straw-man above. However, you're missing the point. These deferred operations actually return results. Generators offer no sane way to pass results back in. If they did, then this use case could be mostly served by generators. -bob ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] Re: anonymous blocks
Guido van Rossum wrote: IMO this is clearer, and even shorter! But it clutters the namespace with objects you don't need. Why do people care about cluttering namespaces so much? I thought thats' what namespaces were for -- to put stuff you want to remember for a bit. A function's local namespace in particular seems a perfectly fine place for temporaries. Indeed. The way people bang on about cluttering namespaces you'd be forgiven for thinking that they are like attics, permanently attached to the house and liable to become cluttered over years. Most function namespaces are in fact extremely short-lived, and there is little point worrying about clutter as long as there's no chance of confusion. regards Steve -- Steve Holden+1 703 861 4237 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ Python Web Programming http://pydish.holdenweb.com/ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
RE: [Python-Dev] Re: switch statement
Andrew McGregor writes: I can post an alternative, inspired by this bit of Haskell [...] The intent is that within the case, the bit before each : is a boolean expression, they're evaluated in order, and the following block is executed for the first one that evaluates to be True. If we're going to be evaluating a series of booleans, then the One Proper Format in Python is: if bool-expr-1: suite-1 elif bool-expr-2: suite-2 elif bool-expr-3: suite-3 else: default-suite When people speak of introducing a switch statement they are speaking of a construct in which the decision of which branch to take requires time proportional to something LESS than a linear function of the number of branches (it's not O(n) in the number of branches). Now the pattern matching is more interesting, but again, I'd need to see a proposed syntax for Python before I could begin to consider it. If I understand it properly, pattern matching in Haskell relies primarily on Haskell's excellent typing system, which is absent in Python. -- Michael Chermside ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Reference counting when entering and exiting scopes
On Wed, 2005-04-20 at 18:59 -0700, Brett C. wrote: So no leak. Yes, there should be more explicit refcounting to be proper, but the compiler cheats in a couple of places for various reasons. But basically everything is fine since st-st_cur and st-st_stack are only played with refcount-wise by either symtable_enter_scope() and symtable_exit_scope() and they are always called in pairs in the end. ... except for the global scope, for which symtable_exit_scope() is never called. But the last reference to *that* scope (st-st_cur) gets cleaned up in PySymtable_Free(). Correct? So the two things I thought were glitches are actually cancelling each other out. Very good. Thanks for your help. Matthew Barnes ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Re: switch statement
Michael Chermside wrote: Now the pattern matching is more interesting, but again, I'd need to see a proposed syntax for Python before I could begin to consider it. If I understand it properly, pattern matching in Haskell relies primarily on Haskell's excellent typing system, which is absent in Python. There's no real need for special syntax in Python - an appropriate tuple subclass will do the trick quite nicely: class pattern(tuple): ignore = object() def __new__(cls, *args): return tuple.__new__(cls, args) def __hash__(self): raise NotImplementedError def __eq__(self, other): if len(self) != len(other): return False for item, other_item in zip(self, other): if item is pattern.ignore: continue if item != other_item: return False return True Py x = (1, 2, 3) Py print x == pattern(1, 2, 3) True Py print x == pattern(1, pattern.ignore, pattern.ignore) True Py print x == pattern(1, pattern.ignore, 3) True Py print x == pattern(2, pattern.ignore, pattern.ignore) False Py print x == pattern(1) False It's not usable in a dict-based switch statement, obviously, but it's perfectly compatible with the current if/elif idiom. Cheers, Nick. -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --- http://boredomandlaziness.skystorm.net ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] Re: Re: anonymous blocks
Bob Ippolito wrote: def strawman(self): def sayGoodbye(mingleResult): def goAway(goodbyeResult): self.loseConnection() self.send(goodbye).addCallback(goAway) def mingle(helloResult): self.send(nice weather we're having).addCallback(sayGoodbye) self.send(hello).addCallback(mingle) def iterman(self): yield hello yield nice weather we're having yield goodbye Which, more or less works, for a literal translation of the straw-man above. However, you're missing the point. These deferred operations actually return results. Generators offer no sane way to pass results back in. that's why you need a context object (=self, in this case). def iterman(self): yield hello print self.data yield nice weather we're having print self.data yield goodbye also see: http://effbot.org/zone/asyncore-generators.htm If they did, then this use case could be mostly served by generators. exactly. /F ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] anonymous blocks
[Greg Ewing] My current thought is that it should look like this: with_file(filename) as f: do_something_with(f) The success of this hinges on how many use cases can be arranged so that the word 'as' makes sense in that position. [...] This way, the syntax is just expr ['as' assignment_target] ':' suite and the expr is evaluated quite normally. Perhaps it could be even simpler: [assignment_target '=']* expr ':' suite This would just be an extension of the regular assignment statement. (More in a longer post I'm composing off-line while picking cherries off the thread.) -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Re: Re: anonymous blocks
Fredrik Lundh wrote: Regardless, I believe that solving generator finalization (calling all enclosing finally blocks in the generator) is a worthwhile problem to solve. Whether that be by PEP 325, 288, 325+288, etc., that should be discussed. Whether people use it as a pseudo-block, or decide that blocks are further worthwhile, I suppose we could wait and see. Agreed. I agree, in fact I think that solving that issue is very important before/if ever introducing a generalized block statement because otherwise things that would naturally be expressible with for and generators will use the block construct which allow more variety and so possibly less immediate clarity just because generators are not good at resource handling. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] anonymous blocks
In case my point about the difference between thunks and other callables (specifically decorators) slipped by, consider the documentation for staticmethod, which takes a callable. All the staticmethod documentation says about that callable's parameters is: A static method does not receive an implicit first argument Pretty simple I'd say. Or classmethod: A class method receives the class as implicit first argument, just like an instance method receives the instance. Again, pretty simple. Why are these simple? Because decorators generally pass on pretty much the same arguments as the callables they wrap. My point was just that because thunks don't wrap other normal callables, they can't make such abbreviations. You've got the special-casing backwards. It's not thinks that are special, but staticmethod (and decorators in general) because they take *any* callable. That's unusual -- most callable arguments have a definite signature, think of map(), filter(), sort() and Button callbacks. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] anonymous blocks
It strikes me that with something like this lexical declaration, we could abuse decorators as per Carl Banks's recipe[1] to get the equivalent of thunks: abuse being the operative word. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] anonymous blocks
On 4/21/05, Guido van Rossum [EMAIL PROTECTED] wrote: It strikes me that with something like this lexical declaration, we could abuse decorators as per Carl Banks's recipe[1] to get the equivalent of thunks: abuse being the operative word. Yup. I was just drawing the parallel between: @withfile(readme.txt) def thunk(fileobj): for line in fileobj: print line and @withfile(readme.txt): # called by withfile as thunk(fileobj=file object) for line in fileobj: print line STeVe -- You can wordify anything if you just verb it. --- Bucky Katt, Get Fuzzy ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Re: switch statement
Samuele Pedroni [EMAIL PROTECTED] writes: Michael Hudson wrote: [pattern matching] Can you post a quick summary of how you think this would work? Well, Python lists are used more imperatively and are not made up with cons cells, we have dictionaries which because of ordering issues are not trivial to match, and no general ordered records with labels. That's a better way of putting it than pattern matching and python don't really seem to fit together, for sure :) (I'd quite like records with labels, tangentially, but am not so wild about ordering) We have objects and not algebraic data types. Literature on the topic usually indicates the visitor pattern as the moral equivalent of pattern matching in an OO-context vs. algebraic data types/functional one. I agree with that point of view and Python has idioms for the visitor pattern. But the visitor pattern is pretty grim, really. It would be nice (tm) to have something like: match node in: Assign(lhs=Var(_), rhs=_): # lhs, rhs bound in here Assign(lhs=Subscr(_,_), rhs=_): # ditto Assign(lhs=Slice(*_), rhs=_): # ditto Assign(lhs=_, rhs=_): raise SyntaxError in Lib/compiler. Vyper had something like this, I think. Interestingly even in the context of objects one can leverage the infrastructure that is there for generalized copying/pickling to allow generalized pattern matching of nested object data structures. Whether it is practical I don't know. class Pt: ... def __init__(self, x,y): ... self.x = x ... self.y = y ... p(lambda _: Pt(1, _()) ).match(Pt(1,3)) (3,) p(lambda _: Pt(1, Pt(_(),_(.match(Pt(1,Pt(Pt(5,6),3))) (__main__.Pt instance at 0x40200b4c, 3) http://codespeak.net/svn/user/pedronis/match.py is an experiment in that direction (preceding this discussion and inspired while reading a book that was using OCaml for its examples). Yikes! Notice that this is quite grossly subclassing pickling infrastracture (the innocent bystander should probably not try that), a cleaner approach redoing that logic with matching in mind is possible and would be preferable. Also, the syntax is disgusting. But that's a separate issue, I guess. Cheers, mwh -- /* I'd just like to take this moment to point out that C has all the expressive power of two dixie cups and a string. */ -- Jamie Zawinski from the xkeycaps source ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] anonymous blocks
Greg Ewing wrote: I also have a thought concerning whether the block argument to the function should come first or last or whatever. My solution is that the function should take exactly *one* argument, which is the block. Any other arguments are dealt with by currying. In other words, with_file above would be defined as def with_file(filename): def func(block): f = open(filename) try: block(f) finally: f.close() return func This would also make implementation much easier. The parser isn't going to know that it's dealing with anything other than a normal expression statement until it gets to the 'as' or ':', by which time going back and radically re-interpreting a previous function call could be awkward. I made an example implementation, and this wasn't an issue. It took some code to stick the thunk into the argument list, but it was pretty straightforward. The syntax that is actually used by the parser can be the same regardless of whether or not argument list augmentation is done, so the parser will not find one more awkward than the other. This way, the syntax is just expr ['as' assignment_target] ':' suite and the expr is evaluated quite normally. Requiring arguments other than the block to be dealt with by currying can lead to problems. I won't claim these problems are serious, but they will be annoying. Say, for example, you create a block-accepting function that takes no arguments. Naturally, you would define it like this: def f(block): do_something_with_block Now, say you want to add to this function an optional argument, so you wrap another function around it like in your 'with_file' example above. Unfortunately, now you need to go find every call of this function and add empty parentheses. This is annoying. Remember the first time you added optional arguments to a function and what a relief it was not to have to go find every call to that function and stick in the extra argument? Those days are over! (well, in this case anyway.) Some people, aware of this problem of adding optional arguments, will define *all* of their block-accepting functions so that they are wrapped in another function, even if that function takes no arguments (and wars, annoying ones, will be fought over whether this is the right way to do it or not!): def f(): def real_func(block): pass return real_func Now the documentation gets confusing. Just saying that the function doesn't take any non-block arguments isn't enough. You would need very specific language, which many library authors will not provide. And there will always be that extra step in thought: do I need the stupid parentheses or not? There will inevitably be people (including me) who get the parentheses wrong because of absentmindedness or carelessness. This will be an extra little speed bump. Now, you may say that all these arguments apply to function decorators, so why have none of these problems appeared? The difference is that defining a function takes a long time, so a little speed bump when decorating it isn't a big deal. But blocks can be defined almost instantly. Much of their purpose has to do with making things quicker. Speed bumps are therefore a bigger deal. This will also be an issue for beginners who use python. A beginner won't necessarily have a good understanding of a function that returns a function. But such an understanding would be required simply to *use* block-accepting functions. Otherwise it would be completely mysterious why sometimes one sees this f(a,b,c) as i: pass and sometimes this g as i: pass even though both of these cases just seem to call the function that appears next to 'as' (imagine you don't have the source of 'f' and 'g'). Even worse, imagine finally learning the rule that parentheses are not allowed if there are zero arguments, and then seeing: h() as i: pass Now it would just seem arbitrary whether or not parentheses are required or disallowed. Such an issue may seem trivial to an experienced programmer, but can be very off-putting for a beginner. Another set of question arose for me when Barry started musing over the combination of blocks and decorators. What are blocks? Well, obviously they are callable. What do they return? The local namespace they created/modified? I think the return value of a block should be None. In constructs like with_file, the block is being used for its side effect, not to compute a value for consumption by the block function. I don't see a great need for blocks to be able to return values. If you google filetype:rb yield, you can see many the uses of yield in ruby. By looking for the uses in which yield's return value is used, you can find blocks that return values. For example, t = yield() or unless yield() indicate that a block is returning a value. It is true that most of the time blocks do not return values, but
[Python-Dev] anonymous blocks
I've been thinking about this a lot, but haven't made much progess. Here's a brain dump. I've been thinking about integrating PEP 325 (Resource-Release Support for Generators) into the for-loop code, so that you could replace the_lock.acquire() try: BODY finally: the_lock.release() with for dummy in synchronized(the_lock): BODY or perhaps even (making for VAR optional in the for-loop syntax) with in synchronized(the_lock): BODY Then synchronized() could be written cleanly as follows: def synchronized(lock): lock.acquire() try: yield None finally: lock.release() But then every for-loop would have to contain an extra try-finally clause; the translation of for VAR in EXPR: BODY would become __it = iter(EXPR) try: while True: try: VAR = __it.next() except StopIteration: break BODY finally: if hasattr(__it, close): __it.close() which I don't particularly like: most for-loops DON'T need this, since they don't use a generator but some other form of iterator, or even if they use a generator, not all generators have a try/finally loop. But the bytecode compiler can't know that, so it will always have to generate this code. It also changes the semantics of using a generator in a for-loop slightly: if you break out of the for-loop before the generator is exhausted you will still get the close() call. It's also a bit funny to see this approach used with the only other use case for try/finally we've looked at, which requires passing a variable into the block: the with_file use case. We now can write with_file as a nice and clean generator: def with_file(filename): f = open(filename) try: yield f finally: f.close() but the use looks very odd because it is syntactically a for-loop but there's only one iteration: for f in with_file(/etc/passwd): for line in f: print line[:line.find(:)] Seeing this example makes me cringe -- why two nested for loops to loop over the lines of one file??? So I think that this is probably not the right thing to pursue, and we might be better off with something along the lines of PEP 310. The authors of PEP 310 agree; under Open Issues they wrote: There are some simiralities in concept between 'with ...' blocks and generators, which have led to proposals that for loops could implement the with block functionality[3]. While neat on some levels, we think that for loops should stick to being loops. (Footnote [3] references the tread that originated PEP 325.) Perhaps the most important lesson we've learned in this thread is that the 'with' keyword proposed in PEP 310 is redundant -- the syntax could just be [VAR '=']* EXPR ':' BODY IOW the regular assignment / expression statement gets an optional colon-plus-suite at the end. So now let's assume we accept PEP 310 with this change. Does this leave any use cases for anonymous blocks uncovered? Ruby's each() pattern is covered by generators; personally I prefer Python's for var in seq: ... over Ruby's much-touted seq.each() {|var| ...} The try/finally use case is covered by PEP 310. (If you want to combine this with a for-loop in a single operation, you'll need PEP 325.) The use cases where the block actually returns a value are probably callbacks for things like sort() or map(); I have to admit that I'd rather keep lambda for these (and use named functions for longer blocks) than introduce an anonymous block syntax that can return values! I also note that if you *already* have a comparison function, Ruby's Array sort method doesn't let you pass it in as a function argument; you have to give it a block that calls the comparison function, because blocks are not the same as callables (and I'm not sure that Ruby even *has* callables -- everything seems to be a block). My tentative conclusion remains: Python doesn't need Ruby blocks. Brian Sabbey ought to come up with more examples rather than arguments why his preferred syntax and semantics are best. --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] anonymous blocks
On Thu, 21 Apr 2005, Guido van Rossum wrote: Perhaps it could be even simpler: [assignment_target '=']* expr ':' suite This would just be an extension of the regular assignment statement. It sounds like you are very close to simply translating expression... function_call(args): suite into expression... function_call(args)(suitefunc) If i understand what you proposed above, you're using assignment as a special case to pass arguments to the inner suite, right? So: inner_args = function_call(outer_args): suite becomes: def suitefunc(inner_args): suite function_call(outer_args)(suitefunc) ? This could get a little hard to understand if the right-hand side of the assignment is more complex than a single function call. I think the meaning would be unambiguous, just non-obvious. The only interpretation i see for this: x = spam('foo') + eggs('bar'): suite is this: def suitefunc(x): suite spam('foo') + eggs('bar')(suitefunc) but that could seem a little too mysterious. Or you could (in a later compiler pass) forbid more complex expressions on the RHS. On another note, would there be any difference between x = spam(): suite and x = spam: suite ? -- ?!ng ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] anonymous blocks
Guido van Rossum wrote: I've been thinking about this a lot, but haven't made much progess. Here's a brain dump. I've been thinking about integrating PEP 325 (Resource-Release Support for Generators) into the for-loop code, so that you could replace [SNIP - using 'for' syntax to delineate the block and resource] So I think that this is probably not the right thing to pursue, I totally agree with your reasoning on this. and we might be better off with something along the lines of PEP 310. The authors of PEP 310 agree; under Open Issues they wrote: There are some simiralities in concept between 'with ...' blocks and generators, which have led to proposals that for loops could implement the with block functionality[3]. While neat on some levels, we think that for loops should stick to being loops. (Footnote [3] references the tread that originated PEP 325.) Perhaps the most important lesson we've learned in this thread is that the 'with' keyword proposed in PEP 310 is redundant -- the syntax could just be [VAR '=']* EXPR ':' BODY IOW the regular assignment / expression statement gets an optional colon-plus-suite at the end. Sure, but is the redundancy *that* bad? You should be able to pick up visually that something is an anonymous block from the indentation but I don't know how obvious it would be. Probably, in the end, this minimal syntax would be fine, but it just seems almost too plain in terms of screaming at me that something special is going on there (the '=' in an odd place just quite cut if for me for my meaning of special). So now let's assume we accept PEP 310 with this change. Does this leave any use cases for anonymous blocks uncovered? Ruby's each() pattern is covered by generators; personally I prefer Python's for var in seq: ... over Ruby's much-touted seq.each() {|var| ...} The try/finally use case is covered by PEP 310. (If you want to combine this with a for-loop in a single operation, you'll need PEP 325.) The use cases where the block actually returns a value are probably callbacks for things like sort() or map(); I have to admit that I'd rather keep lambda for these (and use named functions for longer blocks) than introduce an anonymous block syntax that can return values! I also note that if you *already* have a comparison function, Ruby's Array sort method doesn't let you pass it in as a function argument; you have to give it a block that calls the comparison function, because blocks are not the same as callables (and I'm not sure that Ruby even *has* callables -- everything seems to be a block). My tentative conclusion remains: Python doesn't need Ruby blocks. Brian Sabbey ought to come up with more examples rather than arguments why his preferred syntax and semantics are best. I think I agree with Samuele that it would be more pertinent to put all of this effort into trying to come up with some way to handle cleanup in a generator. -Brett ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] anonymous blocks (don't combine them with generator finalization)
Guido van Rossum [EMAIL PROTECTED] wrote: [Brett] I think I agree with Samuele that it would be more pertinent to put all of this effort into trying to come up with some way to handle cleanup in a generator. I.e. PEP 325. But (as I explained, and you agree) that still doesn't render PEP 310 unnecessary, because abusing the for-loop for implied cleanup semantics is ugly and expensive, and would change generator semantics; and it bugs me that the finally clause's reachability depends on the destructor executing. Yes and no. PEP 325 offers a method to generators that handles cleanup if necessary and calls it close(). Obviously calling it close is a mistake. Actually, calling it anything is a mistake, and trying to combine try/finally handling in generators with __exit__/close (inside or outside of generators) is also a mistake. Start by saying, If a non-finalized generator is garbage collected, it will be finalized. Whether this be by an exception or forcing a return, so be it. If this were to happen, we have generator finalization handled by the garbage collector, and don't need to translate /any/ for loop. As long as the garbage collection requirement is documented, we are covered (yay!). What about ... i.__enter__() try: ... finally: i.__exit__() ... types of things? Well, you seem to have offered a syntax ... [VAR '=']* EXPR: BODY ... which seems to translate into ... [VAR = ] __var = EXPR try: BODY finally: __var.__exit__() ... or something like that. Great! We've got a syntax for resource allocation/freeing outside of generators, and a non-syntax for resource allocation/freeing inside of generators. - Josiah ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] anonymous blocks (don't combine them with generator finalization)
On Apr 21, 2005, at 8:59 PM, Josiah Carlson wrote: Guido van Rossum [EMAIL PROTECTED] wrote: [Brett] I think I agree with Samuele that it would be more pertinent to put all of this effort into trying to come up with some way to handle cleanup in a generator. I.e. PEP 325. But (as I explained, and you agree) that still doesn't render PEP 310 unnecessary, because abusing the for-loop for implied cleanup semantics is ugly and expensive, and would change generator semantics; and it bugs me that the finally clause's reachability depends on the destructor executing. Yes and no. PEP 325 offers a method to generators that handles cleanup if necessary and calls it close(). Obviously calling it close is a mistake. Actually, calling it anything is a mistake, and trying to combine try/finally handling in generators with __exit__/close (inside or outside of generators) is also a mistake. Start by saying, If a non-finalized generator is garbage collected, it will be finalized. Whether this be by an exception or forcing a return, so be it. If this were to happen, we have generator finalization handled by the garbage collector, and don't need to translate /any/ for loop. As long as the garbage collection requirement is documented, we are covered (yay!). Well, for the CPython implementation, couldn't you get away with using garbage collection to do everything? Maybe I'm missing something.. import weakref class ResourceHandle(object): def __init__(self, acquire, release): acquire() # if I understand correctly, this is safer than __del__ self.ref = weakref.ref(self, lambda o:release()) class FakeLock(object): def acquire(self): print acquired def release(self): print released def with_lock(lock): r = ResourceHandle(lock.acquire, lock.release) yield None del r x = with_lock(FakeLock()) del x with_lock(FakeLock()).next() acquired released for ignore in with_lock(FakeLock()): ... print ignore ... acquired None released I could imagine someone complaining about generators that are never used missing out on the acquire/release. That could be solved with a trivial rewrite: def with_lock(lock): def _with_lock(r): yield None del r return _with_lock(ResourceHandle(lock.acquire, lock.release)) x = with_lock(FakeLock()) acquired del x released Of course, this just exaggerates Guido's it bugs me that the finally clause's reachability depends on the destructor executing.. but it does work, in CPython. It seems to me that this pattern would be painless enough to use without a syntax change... -bob ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] anonymous blocks
On Thu, Apr 21, 2005, Guido van Rossum wrote: Perhaps the most important lesson we've learned in this thread is that the 'with' keyword proposed in PEP 310 is redundant -- the syntax could just be [VAR '=']* EXPR ':' BODY IOW the regular assignment / expression statement gets an optional colon-plus-suite at the end. Yes, it could. The question then becomes whether it should. Because it's easy to indent Python code when you're not using a block (consider function calls with lots of args), my opinion is that like the optional colon after ``for`` and ``if``, the resource block *should* have a keyword. -- Aahz ([EMAIL PROTECTED]) * http://www.pythoncraft.com/ The joy of coding Python should be in seeing short, concise, readable classes that express a lot of action in a small amount of clear code -- not in reams of trivial code that bores the reader to death. --GvR ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] anonymous blocks
Guido or perhaps even (making for VAR optional in the for-loop syntax) Guido with Guido in synchronized(the_lock): Guido BODY This could be a new statement, so the problematic issue of implicit try/finally in every for statement wouldn't be necessary. That complication would only be needed for the above form. (Of course, if you've dispensed with this I am very likely missing something fundamental.) Skip ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] anonymous blocks
Ka-Ping Yee wrote: It seems to me that, in general, Python likes to use keywords for statements and operators for expressions. Probably worth noting that 'for', 'in' and 'if' in generator expressions and list comprehensions blur this distinction somewhat... Steve -- You can wordify anything if you just verb it. --- Bucky Katt, Get Fuzzy ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Re: switch statement
At 06:10 PM 04/21/2005 +0100, Michael Hudson wrote: But the visitor pattern is pretty grim, really. It would be nice (tm) to have something like: match node in: Assign(lhs=Var(_), rhs=_): # lhs, rhs bound in here Assign(lhs=Subscr(_,_), rhs=_): # ditto Assign(lhs=Slice(*_), rhs=_): # ditto Assign(lhs=_, rhs=_): raise SyntaxError in Lib/compiler. FWIW, I do intend to add this sort of thing to PyProtocols' predicate dispatch system. Actually, I can dispatch on rules like the above now, it's just that you have to spell out the cases as e.g.: @do_it.when(isinstance(node, Assign) and isinstance(node.lhs, Subscr)) def do_subscript_assign(node, ...): ... I'd like to create a syntax sugar for pattern matching though, that would let you 1) use a less verbose way of saying the same thing, and 2) let you bind the intermediate values to variables that then become accessible in the function body as locals. Anyway, the main holdup on this is deciding what sort of Python syntax abuse should represent variable bindings. :) Maybe something like this will be suitably horrific: @do_it.when(node in Assign.match(lhs=`lhs` in Subscr,rhs=`rhs`)) def do_subscript_assign((lhs,rhs), node, ...): ... But I think maybe here the cure is worse than the disease. :) Pushed this far, it seems to beg for new syntax to accommodate in-expression variable bindings, something like 'var:=value'. Really, though, the problem is probably just that inline variable binding is downright unpythonic. The only time Python does anything vaguely similar is with the 'except type,var:' syntax. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] anonymous blocks
Guido van Rossum wrote: [Brett] I think I agree with Samuele that it would be more pertinent to put all of this effort into trying to come up with some way to handle cleanup in a generator. I.e. PEP 325. But (as I explained, and you agree) that still doesn't render PEP 310 unnecessary, because abusing the for-loop for implied cleanup semantics is ugly and expensive, and would change generator semantics; Right, I'm not saying PEP 310 shouldn't also be considered. It just seems like we are beginning to pile a lot on this discussion by bringing in PEP 310 and PEP 325 in at the same time since, as pointed out, there is no guarantee that anything will be called in a generator and thus making PEP 310 work in generators does not seem guaranteed to solve that problem (although I might have missed something; just started really following the thread today). At this point anonymous blocks just don't seem to be happening, at least not like in Ruby. Fine, I didn't want them anyway. Now we are trying to simplify resource cleanup and handling. What I am trying to say is that generators differ just enough as to possibly warrant a separate discussion from all of this other resource handling stuff. So I am advocating a more focused generator discussion since resource handling in generators is much more difficult than the general case in non-generator situations. I mean obviously in the general case all of this is handled already in Python today with try/finally. But with generators you have to jump through some extra hoops to get similar support (passing in anything that needs to be cleaned up, hoping that garbage collection will eventually handle things, etc.). and it bugs me that the finally clause's reachability depends on the destructor executing. Yeah, I don't like it either. I would rather see something like: def gen(): FILE = open(stuff.txt, 'rU') for line in FILE: yield line cleanup: FILE.close() and have whatever is in the 'cleanup' block be either accessible from a method in the generator or have it become the equivalent of a __del__ for the generator, or maybe even both (which would remove contention that whatever needs to be cleaned up is done too late thanks to gc not guaranteeing immediate cleanup). This way you get the guaranteed cleanup regardless and you don't have to worry about creating everything outside of the generator, passing it in, and then handling cleanup in a try/finally that contains the next() calls to the generator (or any other contortion you might have to go through). Anyway, my random Python suggestion for the day. -Brett ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] anonymous blocks (don't combine them with generator finalization)
Bob Ippolito wrote: On Apr 21, 2005, at 8:59 PM, Josiah Carlson wrote: Guido van Rossum [EMAIL PROTECTED] wrote: [Brett] I think I agree with Samuele that it would be more pertinent to put all of this effort into trying to come up with some way to handle cleanup in a generator. I.e. PEP 325. But (as I explained, and you agree) that still doesn't render PEP 310 unnecessary, because abusing the for-loop for implied cleanup semantics is ugly and expensive, and would change generator semantics; and it bugs me that the finally clause's reachability depends on the destructor executing. Yes and no. PEP 325 offers a method to generators that handles cleanup if necessary and calls it close(). Obviously calling it close is a mistake. Actually, calling it anything is a mistake, and trying to combine try/finally handling in generators with __exit__/close (inside or outside of generators) is also a mistake. Start by saying, If a non-finalized generator is garbage collected, it will be finalized. Whether this be by an exception or forcing a return, so be it. If this were to happen, we have generator finalization handled by the garbage collector, and don't need to translate /any/ for loop. As long as the garbage collection requirement is documented, we are covered (yay!). Well, for the CPython implementation, couldn't you get away with using garbage collection to do everything? Maybe I'm missing something.. [SNIP] Well, if you are missing something then so am I since your suggestion is basically correct. The only issue is that people will want more immediate execution of the cleanup code which gc cannot guarantee. That's why the ability to call a method with the PEP 325 approach gets rid of that worry. -Brett ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] anonymous blocks (don't combine them with generator finalization)
On Apr 22, 2005, at 12:28 AM, Brett C. wrote: Bob Ippolito wrote: On Apr 21, 2005, at 8:59 PM, Josiah Carlson wrote: Guido van Rossum [EMAIL PROTECTED] wrote: [Brett] I think I agree with Samuele that it would be more pertinent to put all of this effort into trying to come up with some way to handle cleanup in a generator. I.e. PEP 325. But (as I explained, and you agree) that still doesn't render PEP 310 unnecessary, because abusing the for-loop for implied cleanup semantics is ugly and expensive, and would change generator semantics; and it bugs me that the finally clause's reachability depends on the destructor executing. Yes and no. PEP 325 offers a method to generators that handles cleanup if necessary and calls it close(). Obviously calling it close is a mistake. Actually, calling it anything is a mistake, and trying to combine try/finally handling in generators with __exit__/close (inside or outside of generators) is also a mistake. Start by saying, If a non-finalized generator is garbage collected, it will be finalized. Whether this be by an exception or forcing a return, so be it. If this were to happen, we have generator finalization handled by the garbage collector, and don't need to translate /any/ for loop. As long as the garbage collection requirement is documented, we are covered (yay!). Well, for the CPython implementation, couldn't you get away with using garbage collection to do everything? Maybe I'm missing something.. [SNIP] Well, if you are missing something then so am I since your suggestion is basically correct. The only issue is that people will want more immediate execution of the cleanup code which gc cannot guarantee. That's why the ability to call a method with the PEP 325 approach gets rid of that worry. Well in CPython, if you are never assigning the generator to any local or global, then you should be guaranteed that it gets cleaned up at the right time unless it's alive in a traceback somewhere (maybe you WANT it to be!) or some insane trace hook keeps too many references to frames around.. It seems *reasonably* certain that for reasonable uses this solution WILL clean it up optimistically. -bob ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Proper place to put extra args for building
Martin v. Lwis wrote: Brett C. wrote: Works for me. If no one objects I will check in the change for CFLAGS to make it ``$(BASECFLAGS) $(OPT) $EXTRA_CFLAGS`` soon (is quoting it enough to make sure that it isn't evaluated by configure but left as a string to be evaluated by the shell when the Makefile is running?). If you put it into Makefile.pre.in, the only thing to avoid that configure evaluates is is not to use @[EMAIL PROTECTED] OTOH, putting a $ in front of it is not good enough for make: $EXTRA_CFLAGS evaluates the variable E, and then appends XTRA_CFLAGS. Yep, you're right. I initially thought that the parentheses meant it was a Makefile-only variable, but it actually goes to the environment for those unknown values. Before I check it in, though, should setup.py be tweaked to use it as well? I say yes. -Brett ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com