Re: Simple HTML template engine?
Have you tried CherryPy? http://www.cherrypy.org/ It's not a template engine, but a simple web server engine, and you could code your conditionals and loops directly in Python... When I have tried it, it looked very nice and easy. Ciprian. On 10/15/07, allen.fowler <[EMAIL PROTECTED]> wrote: > Hello, > > Can anyone recommend a simple python template engine for generating > HTML that relies only on the Pyhon Core modules? > > No need for caching, template compilation, etc. > > Speed is not a major issue. > > I just need looping and conditionals. Template inheritance would be a > bonus. > > I've seen Genshi and Cheetah, but they seem way too complex. > > Any ideas? > > I'm sure I could build something myself, but I'm sure this has already > been done quite a few times. Why re-invent the wheel, right? > > > Thank you, > Allen -- http://mail.python.org/mailman/listinfo/python-list
Re: Perl / python regex / performance comparison
On Tue, Mar 3, 2009 at 7:03 PM, Ivan wrote: > Hello everyone, > > I know this is not a direct python question, forgive me for that, but > maybe some of you will still be able to help me. I've been told that > for my application it would be best to learn a scripting language, so > I looked around and found perl and python to be the nice. Their syntax > and "way" is not similar, though. > So, I was wondering, could any of you please elaborate on the > following, as to ease my dilemma: > > 1. Although it is all relatively similar, there are differences > between regexes of these two. Which do you believe is the more > powerful variant (maybe an example) ? > > 2. They are both interpreted languages, and I can't really be sure how > they measure in speed. In your opinion, for handling large files, > which is better ? > (I'm processing files of numerical data of several hundred mb - let's > say 200mb - how would python handle file of such size ? As compared to > perl ?) > > 3. This last one is somewhat subjective, but what do you think, in the > future, which will be more useful. Which, in your (humble) opinion > "has a future" ? > > Thank you for all the info you can spare, and expecially grateful for > the time in doing so. > -- Ivan > -- > http://mail.python.org/mailman/listinfo/python-list I could answer to your second question (will Python handle large files). In my case I use Python to create statistics from some trace files from a genetic algorithm, and my current size is up to 20MB for about 40 files. I do the following: * use regular expressions to identify each line type, extract the information (as numbers); * either create statistics on the fly, either load the dumped data into an Sqlite3 database (which got up to a couple of hundred MB); * everything works fine until now; I've also used Python (better said an application built in Python with cElementTree?), that took the Wikipedia XML dumps (7GB? I'm not sure, but a couple of GB), then created a custom format file, from which I've tried to create SQL inserts... And everything worked good. (Of course it took some time to do all the processing). So my conclusion is that if you try to keep your in-memory data small, and use the smart (right) solution for the problem you could use Python without (big) overhead. Another side-note, I've also used Python (with NumPy) to implement neural networks (in fact clustering with ART), where I had about 20 thousand training elements (arrays of thousands of elements), and it worked remarkably good (I would better than in Java, and comparable with C/C++). I hope I've helped you, Ciprian Craciun. P.S. If you just need one regular expression transformation to another, or you need regular expression searching, then just use sed or grep as you would not get anything better than them. -- http://mail.python.org/mailman/listinfo/python-list
Re: Lisp mentality vs. Python mentality
On Sat, Apr 25, 2009 at 9:06 AM, Carl Banks wrote: > In answering the recent question by Mark Tarver, I think I finally hit > on why Lisp programmers are the way they are (in particular, why they > are often so hostile to the "There should only be one obvious way to > do it" Zen). > > Say you put this task to a Lisp and a Python programmer: Come up with > a good, generic, reusable way to compare two lists. What are their > respective trains of thought? > > > Lisp programmer: > > Well, there is a standard function called mismatch that does it, but I > can't recommend it. First of all, you don't know where that > function's been. Anyone and their mother could have worked on it, did > they have good, sound programming practice in mind when they wrote > it? Of course not. Let's be real here, we have to implement this by > hand. > > (defun lists-are-equal (a b) > (or (and (not a) (not b)) > (and (= (car a) (car b)) (lists-are-equal (cdr a) (cdr b > > There, much better than the standard function, and better yet, it's in > the *absolute minimal form possible*. There is no way to express list > comparison in a more reduced form. It's almost erotic how awesome it > is. I'm---whoa, ok, I'm getting a little excited now, settle down. > Well, come to think of it, that's really not that good. First of all > it's a function. I mean, it just sits there and does nothing till you > call it. How boring is that? It can't react to the current > situation. Plus it compares all lists the same way, and that is > really inefficient. Every list compare is a new problem. Different > lists need different comparative strategies. This function simply > won't do. I need a macro that can intelligently compile the right > list compare methodology in. For instance, if we want to compare two > lists that are known at compile time, we don't want to waste time > comparing them at runtime. No, the macro must detect constant > arguments and special case them. Good start. Now, we have to > consider the conditions this comparison is being done under. If the > user is passing the result of a sort to this macro, it's almost > certain that they are trying to see whether the lists have the same > elements. We can do that a lot more efficiently with a countset. So > let's have the macro check to see if the forms passed to it are all > sort calls. Better yet, let's check for my own powerful sort macro. > Hmm. Wait... I think my 4600-line sort macro already checks its > calling context to see if its results are being fed to a list > comparison. I'll have to refactor that together with this macro. Ok, > good, now I am sure other users will eventually want to customize list > comparison for their own use, after all every list comparison is > different and I can't possibly anticipate all of them. A user needs > to be able to adapt to the situation, so it's vitally important to > create a plug-in infrastructure to give them that flexibility. Now, > what about exceptions, there's a millions ways to deal with that... > > ...and so on until eyelids can no longer stay open > > > > Python programmer: > > a == b. Next question. > > > > Carl Banks, who might be exaggerating > > ...a little. > -- > http://mail.python.org/mailman/listinfo/python-list Well, if you opened the Pandora's box, lets see how can we implement this both ways... The Scheme way (a little more verbose but clearer I would say): (define (compare a b (comp eq?)) (cond ((and (null? a) (null? b) #t)) ((or (null? a) (null? b) #f)) ((and (comp (first a) (first b))) (compare (rest a) (rest b) comp)) (else #f))) (compare '(1 2 3) '(1 2 3)) (compare '(1 "a" 3) '(1 "a" 3) equal?) (compare '(1 2 3) '(1 2 4) <=) - Python way: - def eq (a, b) : return a == b def compare (a, b, comp = eq) : if len (a) != len (b) : return False for i in xrange (len (a)) : if not comp (a[i], b[i]) : return False return True compare ([1, 2, 3], [1, 2, 3]) - I don't see another way... (Or at least another more different way...) Which is best? None: * they both work in linear time (except the Python implementation checks the length first); * they are both compact and readable; * they are both expandable; Personally I like best the Scheme version, because for example I can use it like (compare '(1 2 3) '(1 2 4) <=) to compare for less or equal in case of vectors. In the case of Python I would have needed to write compare ([1, 2, 3], [1, 2, 4], lambda a, b : a <= b) Ciprian Craciun. P.S.: I think of this as a challenge for hackers in both languages to come up with the most estetic, optimal and useful implementation... (My implementations are just toys...) -- http://mail.python.org/mailman/listinfo/python-list
Re: Lisp mentality vs. Python mentality
On Sat, Apr 25, 2009 at 10:43 AM, wrote: > Ciprian Dorin, Craciun: >> Python way: >> - >> def eq (a, b) : >> return a == b >> >> def compare (a, b, comp = eq) : >> if len (a) != len (b) : >> return False >> for i in xrange (len (a)) : >> if not comp (a[i], b[i]) : >> return False >> return True > > That's not "pythonic". > > Bye, > bearophile > -- > http://mail.python.org/mailman/listinfo/python-list Ok... Then what's pythonic? Please give a pythonic implementation... Ciprian Craciun. P.S.: Also, I'm tired of hearing about the pythonic way... Where do I find a definitive description about the pythonic way? I think that this word is used only when someone sees something that he doesn't like, he doesn't know what he doesn't like at it, and just goes to say its un-pythonic, without saying what would be... Wouldn't be just easier to say "I don't know" or "I doesn't feel right to me"? -- http://mail.python.org/mailman/listinfo/python-list
Re: Lisp mentality vs. Python mentality
On Sat, Apr 25, 2009 at 11:04 AM, Paul Rubin <http://phr...@nospam.invalid> wrote: > "Ciprian Dorin, Craciun" writes: >> Ok... Then what's pythonic? Please give a pythonic implementation... > > Use the builtin a==b, similar to (equal a b) But how about extensibility? -- http://mail.python.org/mailman/listinfo/python-list
Re: Lisp mentality vs. Python mentality
On Sat, Apr 25, 2009 at 11:30 AM, "Martin v. Löwis" wrote: Ok... Then what's pythonic? Please give a pythonic implementation... >>> Use the builtin a==b, similar to (equal a b) >> >> But how about extensibility? > [...] > > I see that you allow for a different comparison function. I do wonder > what the use case for this is - in what application do you have to > compare two lists for equality, and the item's __eq__ is inappropriate? > What would break if you fix the item's __eq__, instead of writing > your own comparison algorithm? > > [...] A practical example: I have lists that contain strings, but I want to compare them in an case-insensitive way... Should I update the __eq__ method (for str class) and break almost everything? Can I write now a == b? Nop... I need the loop you've just mentioned in all the places where the comparison changes just in the operator, not in the algorithm... (I would say this is bad coding practice...) -- http://mail.python.org/mailman/listinfo/python-list
Re: Lisp mentality vs. Python mentality
On Sat, Apr 25, 2009 at 11:36 AM, "Martin v. Löwis" wrote: >> I don't get that impression from Lisp programmers. > > I observe a phenomenon on language fanatics, no matter what language, > but in particular for the less-than-mainstream language: the desire > to formulate trivial algorithms over and over again, just to enjoy the > beauty of the result (and sometimes the mere fact of being able to do > so). > > I suppose people writing real applications in LISP have better things > to spend time on. > > Regards, > Martin Yes, you're right, Lisp people have better things to do, because these algorithms are already implemented for them: just see ormap and andmap functions that do just what we wanted... http://download.plt-scheme.org/doc/html/reference/pairs.html#(def._((quote._~23~25kernel)._ormap)) http://download.plt-scheme.org/doc/html/reference/pairs.html#(def._((lib._scheme/private/map..ss)._andmap)) Ciprian. P.S.: I'm not a language fanatic... I programmed both in Python and Scheme (mostly in Python)... P.P.S.: I'm just trying to see why is Python better than Lisp or vice-versa... I would say they are almost the same: both usable for day-to-day real world applications... -- http://mail.python.org/mailman/listinfo/python-list
Re: Lisp mentality vs. Python mentality
On Sat, Apr 25, 2009 at 1:55 PM, "Martin v. Löwis" wrote: >> A practical example: I have lists that contain strings, but I want >> to compare them in an case-insensitive way... > > I'd claim that this is still theoretical: what are these strings, and > why do you have lists of them that you want to compare? > > Why don't you try to lower-case the strings in the list as you > add them? > > Also, are you sure a list is the best data structure for your problem? > Perhaps using a set would be better? Indeed the example I've given is purely theoretical. But still, I could find a use case for such a thing: just imagine we are building a small shell-like application that reads one line (the commands), splits it by spaces and always expects to have 4 elements and that each respects a given regular expression, one specific for each index. In this case I could syntactically check for correctness by doing this: compare (regular_expressions, splitted_line, re.match) Of course I could have just created a big regular expression for the entire line. But maybe my 4 elements come from variables obtained from a web-server query, or the regular expressions are not static but dynamically generated at run-time. >> Should I update the >> __eq__ method (for str class) and break almost everything? Can I write >> now a == b? Nop... I need the loop you've just mentioned in all the >> places where the comparison changes just in the operator, not in the >> algorithm... (I would say this is bad coding practice...) > > If you want to compare the same lists in many places, this is indeed > bad coding practice. You should try to centralize whatever reasons > you have for comparing the lists into a few methods of the objects > holding the lists. > > Regards, > Martin I like object oriented programming, but most of the times we are just throwing together code and data even when the data has no behavior and the code is in fact just one possible processing algorithm. Like in the case you are mentioning, if I tie the comparison code to the actual data structure, then I'll never be able to reuse it... But if I leave the code as a standalone function, and just use the data (or any data that resembles the original structure) then maybe I'll be able to reuse it... Ciprian. -- http://mail.python.org/mailman/listinfo/python-list
Re: Lisp mentality vs. Python mentality
On Sat, Apr 25, 2009 at 4:01 PM, "Martin v. Löwis" wrote: >> Indeed the example I've given is purely theoretical. But still, I >> could find a use case for such a thing: just imagine we are building a >> small shell-like application that reads one line (the commands), >> splits it by spaces and always expects to have 4 elements and that >> each respects a given regular expression, one specific for each index. >> In this case I could syntactically check for correctness by doing >> this: >> >> compare (regular_expressions, splitted_line, re.match) >> >> Of course I could have just created a big regular expression for >> the entire line. But maybe my 4 elements come from variables obtained >> from a web-server query, or the regular expressions are not static but >> dynamically generated at run-time. > > Ok, in this case I would write a function: > > def validate_commandline(rexes, line): > if len(rexes) != len(line): > raise ValueError("Incorrect number of arguments, expected %d," > "got %d" % (len(rexes), len(line))) > for i in range(len(line)): > if not re.match(rexes[i], line[i]): > raise ValueError, "Incorrect argument %d" % i > > IOW, in this specific case, I would not only want a true/false result, > but also an indication of the actual error to report to the user. > Your universal compare function would be no good here. > > Regards, > Martin > Well in fact I would have written it like: def validate_commandline(rexes, line) : if not compare (rexes, line, re.match) : if len (rexes) != len (line) : raise ValueError ("mismatch len") mismatch = find_index (rexes, line, re.match, negate = True) raise ValueError ("mismatch at %d" % (mismatch)) Assuming, that I would have the function find_index. Ciprian. -- http://mail.python.org/mailman/listinfo/python-list
Re: Lisp mentality vs. Python mentality
On Sat, Apr 25, 2009 at 11:36 PM, Brett Hoerner wrote: > On Apr 25, 8:11 am, "Ciprian Dorin, Craciun" > wrote: >> Well in fact I would have written it like: >> >> def validate_commandline(rexes, line) : >> if not compare (rexes, line, re.match) : >> if len (rexes) != len (line) : >> raise ValueError ("mismatch len") >> mismatch = find_index (rexes, line, re.match, negate = True) >> raise ValueError ("mismatch at %d" % (mismatch)) >> >> Assuming, that I would have the function find_index. >> >> Ciprian. > > I think you've hit on the definition of "unpythonic". (No, I don't > have a dictionary definition for you, sorry). > > Using a function called "compare" to run a list of regexes against > another list of regexes to get a boolean? And then another find_index > function doing the same where you pass in negate? What is even going > on here? > > I, for one, would take Martin's any day of the week. It reads like > good pseudocode as much "proper" Python does. > > Brett From your comments I understand that the only problem with my code proposal are the function names... Well instead of compare (which was kept from the beginning of the post) we could just rename it to "matches". Does the name "matches" matches what it does? :) (If not we can keep discussing for a proper name...) And about the find_index, we could rename it to first_matching_index. About the negation optional parameter, we could eliminate it if we allow either: to have another function first_missmatching_index, but this leads to namespace bloat, or we have a function named negate, that takes another function, and negates it meaning. (Although i don't see anything wrong in the negate argument... It's just like having order by asc | desc in SQL...) Thus the code would have been rewritten as: (we also put the function on the first argument as its the most important argument) def validate_commandline(rexes, line) : if not matches (re.match, rexes, line) : if len (rexes) != len (line) : raise ValueError ("mismatch len") mismatch = first_matching_index (negate (re.match), rexes, line) raise ValueError ("mismatch at %d" % (mismatch)) Ciprian. -- http://mail.python.org/mailman/listinfo/python-list
Re: Lisp mentality vs. Python mentality
On Sun, Apr 26, 2009 at 7:54 AM, Steven D'Aprano wrote: > On Sat, 25 Apr 2009 10:50:50 +0300, Ciprian Dorin, Craciun wrote: > >> On Sat, Apr 25, 2009 at 10:43 AM, wrote: >>> Ciprian Dorin, Craciun: >>>> Python way: >>>> - >>>> def eq (a, b) : >>>> return a == b >>>> >>>> def compare (a, b, comp = eq) : >>>> if len (a) != len (b) : >>>> return False >>>> for i in xrange (len (a)) : >>>> if not comp (a[i], b[i]) : >>>> return False >>>> return True >>> >>> That's not "pythonic". >>> >>> Bye, >>> bearophile >>> -- >>> http://mail.python.org/mailman/listinfo/python-list >> >> Ok... Then what's pythonic? Please give a pythonic implementation... > > Don't re-invent the wheel. Instead of creating your own functions, use > existing tools to your advantage. > > import operator > > def compare(a, b, comp=operator.eq): > if len(a) != len(b): > return False > for a, b in zip(a, b): > if not comp(a[i], b[i]): > return False > return True > > > But we can re-write that to be even more pythonic, by using the built-in > all(): > > def compare(a, b, comp=operator.eq): > if len(a) != len(b): > return False > return all(comp(x, y) for (x, y) in zip(a, b)) > > or even: > > def compare(a, b, comp=operator.eq): > return (len(a) == len(b)) and all(comp(*t) for t in zip(a, b)) > > > (All the above are untested, so please excuse any errors.) > > >> Ciprian Craciun. >> >> P.S.: Also, I'm tired of hearing about the pythonic way... Where >> do I find a definitive description about the pythonic way? > > There is no such thing as a definitive description of pythonic -- it is > like art, and pornography: you can recognise it when you see it (except > when you can't). > > However, you can get close by doing: > > import this > > in the Python interactive interpreter. Or from a shell prompt: > > python -m this > > >> I think that >> this word is used only when someone sees something that he doesn't like, >> he doesn't know what he doesn't like at it, and just goes to say its >> un-pythonic, without saying what would be... Wouldn't be just easier to >> say "I don't know" or "I doesn't feel right to me"? > > I think that there's a risk that people over-use unpythonic when they > mean "I don't like it", but that doesn't mean that pythonic isn't a > meaningful concept. However, it is a matter of degree, not kind: like > mole-hills and mountains, unpythonic and pythonic are very different > things, but there's no precise dividing line between them. > > > -- > Steven I liked very much your implementation for the compare function, it is very short and at the same time readable: > def compare(a, b, comp=operator.eq): > return (len(a) == len(b)) and all(comp(*t) for t in zip(a, b)) But I have only one problem, it is suboptimal, in the sense that: * it constructs two intermediary lists (the list comprehension and the zip call); * it evaluates all the elements, even if one is false at the beginning; So, could you overcome these problems? About the pythonic vs unpythonic words, I agree with you, there are ofter overused and misused... Ciprian. -- http://mail.python.org/mailman/listinfo/python-list
Re: Lisp mentality vs. Python mentality
On Sun, Apr 26, 2009 at 8:11 AM, Steven D'Aprano wrote: > On Sat, 25 Apr 2009 10:30:56 +0200, Martin v. Löwis wrote: > > Ok... Then what's pythonic? Please give a pythonic > implementation... Use the builtin a==b, similar to (equal a b) >>> >>> But how about extensibility? >> >> == is extensible. To compare two things for equality, use ==. >> >> This is what Carl Banks referred in his original posting. You just >> *don't* implement a function that compares two lists, not even as an >> exercise for estetic, optimal, and useful implementations - because >> you'll know that it won't be useful, anyway, if you can already use the >> builtin == in the first place. >> >> I see that you allow for a different comparison function. I do wonder >> what the use case for this is - in what application do you have to >> compare two lists for equality, and the item's __eq__ is inappropriate? > > The above doesn't really compare for equality, it's a generic element-by- > element comparison function, and so it is inappropriate to contrast it to > __eq__ alone. Defaulting to equality testing is misleading, and if I were > writing such a function I'd remove the default. > > compare(a, b, operator.eq) gives the same result as the simpler a == b, > but compare(a, b, operator.lt) does something very different to a < b. I > can't think of an application for element-by-element comparisons off the > top of my head, but if the numpy people use it, there must be a need :) > > > -- > Steven > -- I agree with your comment, the presented function compare does more than this, in fact checks if the elements in the two functions match a given binary predicate. (In Scheme this is named "andmap") About the compare (a, b, operator.lt) it does the same as a < b, where a and b are lists of numbers. An usage for the compare function (as I've shown in a previous post to this thread) could also have been checking a list of strings if they match to a list of regular expressions (we rename the function compare to the name "match" as it is much general): match (re.match, regexps, strings) About the defaults, I really, really, agree with your comment: "Defaulting to equality testing is misleading"... Most of the times equality means equality by value, but sometimes you need the equality to be more relaxed (maybe ignore case, maybe ignore spaces, or maybe for real numbers to ignore a difference smaller than a chosen delta (those writing scientific applications know this too well))... Ciprian. -- http://mail.python.org/mailman/listinfo/python-list
Re: Lisp mentality vs. Python mentality
On Sun, Apr 26, 2009 at 12:08 PM, "Martin v. Löwis" wrote: >> From your comments I understand that the only problem with my code >> proposal are the function names... > > No, the problem is that you are using way too many functions, that do > too little. The problem with that is then that you have to give names > to all the functions, which then find people difficult to read because > they don't just need to the code in question itself; they also need to > dozen of helper functions that it relies on. > >> And about the find_index, we could rename it to >> first_matching_index. About the negation optional parameter, we could >> eliminate it if we allow either: to have another function >> first_missmatching_index, but this leads to namespace bloat, or we >> have a function named negate, that takes another function, and negates >> it meaning. > > Or you could avoid introducing the function altogether, to make it more > readable. This makes it more pythonic, also: readability counts (from > the Zen of Python). > > Regards, > Martin So if I'm reading right you are saying something in the lines: "using too many functions is bad just because it is unreadable and non-understandable to average (could I say mediocre?) programmers"... Unfortunately I thought that delegating responsibilities to other functions, and thus writing small chunks of code, is what good software engineering is... Well my bad... (As a side-note, maybe this is a reason why some of my students find it hard to understand functional programming -- too many functions that is -- I shall have to revise my teaching, and tell the students to inline everything, maybe they'll understand it like this :) ) Although you have a point -- that of being hard to comprehend by average programmers -- but this doesn't mean it is a wrong (as in ugly) solution... Also, with respects, but the "pythonic" solution involving generators (or iterators) and "zip" or "all" function -- although I appreciate it as it comes close to FP -- is not what I would call readable and understandable by non-guru programmers... Ciprian Craciun. -- http://mail.python.org/mailman/listinfo/python-list
Re: Lisp mentality vs. Python mentality
On Mon, Apr 27, 2009 at 2:14 AM, Dan Sommers wrote: > On Sun, 26 Apr 2009 12:30:40 +0300, Ciprian Dorin, Craciun wrote: > >> On Sun, Apr 26, 2009 at 12:08 PM, "Martin v. Löwis" >> wrote: > >>> No, the problem is that you are using way too many functions, that do >>> too little. The problem with that is then that you have to give names >>> to all the functions, which then find people difficult to read because >>> they don't just need to the code in question itself; they also need to >>> dozen of helper functions that it relies on. > >>> Or you could avoid introducing the function altogether, to make it more >>> readable. This makes it more pythonic, also: readability counts (from >>> the Zen of Python). > >> So if I'm reading right you are saying something in the lines: >> "using too many functions is bad just because it is unreadable and >> non-understandable to average (could I say mediocre?) programmers"... >> Unfortunately I thought that delegating responsibilities to other >> functions, and thus writing small chunks of code, is what good software >> engineering is... Well my bad... > > Also from the Zen: flat is better than nested. One of the aspects of > flatter call trees and object hierarchies is that I hit the bottom > (language features or the standard library) sooner, and I "should" > already have the language and its standard library in my brain. That > said, I also tend to break my programs into layers, but I do try to make > each layer as thin as possible (but no thinner). I agree with your opinion about keeping the abstraction layers shallow, but in my view high-order and helper functions do not comprise a new abstraction layer. For example in Lisp, using map, reduce (fold), or any other high-order function is just like using for, or while in a normal imperative language. Another example is the simple Observer pattern. How many think of it as a new layer? Instead anytime we see a method that is named add_listener we already have an idea of what it does... So we could say that in FP world there are some patterns that involve "delegating control" to them. And also I would like to point out that "hitting the language sooner", means to know every function in the standard Python library (which is by far uncomprehensible, its huge) and most of the times you also need the documentation. And if we go this path, when debugging we could use a smart IDE, which should show as tool-tip-text for function names their documentation, and in this way all we have to do to understand a particular function is just to point it out. Ciprian. >> Although you have a point -- that of being hard to comprehend by >> average programmers -- but this doesn't mean it is a wrong (as in ugly) >> solution... Also, with respects, but the "pythonic" solution involving >> generators (or iterators) and "zip" or "all" function -- although I >> appreciate it as it comes close to FP -- is not what I would call >> readable and understandable by non-guru programmers... > > I finally got it through my thick head that I've been *doing* functional > programming with [*nix] shells and pipes for years, well back into my non- > guru days. > > Dan > > -- > Dan Sommers A death spiral goes clock- > <http://www.tombstonezero.net/dan/> wise north of the equator. > Atoms are not things. -- Werner Heisenberg -- Dilbert's PHB -- http://mail.python.org/mailman/listinfo/python-list