Re: reading file to list
William James schrieb: André Thieme wrote: You make a very strong case that Lisp is very feeble at processing data. I'm almost convinced. I somehow don’t believe you :-) Ruby isn't feeble, so data like this is fine: shall we begin? or lotus135? 1984 times! The 3 stooges: COBOL,LISP,FORTRAN. 3.14, si11y L00KING Extracting the unsigned integers: IO.readlines('data').map{|s| s.scan(/\d+/).map{|s| s.to_i}} ==[[], [135, 1984], [3], [3, 14, 11, 0]] Just take the program I posted before and replace (.split % \\s) with (re-seq #\d+ %) Now that I was so kind to give you what you asked for, you will probably do the same for me and show me your Ruby code, in which you define a variable that contains the Fibonacci sequence. (def fibs (lazy-cat [0 1] (map + fibs (drop 1 fibs (nth fibs 70) == 190392490709135 One requirement is that when you look at the n'th fib the results up to n must be memoized, so that nothing needs to be calculated again when you ask for a fib between 0 and n. And when you ask for the n+1'th it will start the calculation right from point n. Example: user (time (nth fibs 900)) Elapsed time: 16.898726 msecs user (time (nth fibs 901)) Elapsed time: 0.268603 msecs André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: reading file to list
Xah Lee schrieb: comp.lang.lisp,comp.lang.scheme,comp.lang.functional,comp.lang.python,comp.lang.ruby Here's a interesting toy problem posted by Drew Krause to comp.lang.lisp: On Jan 16, 2:29 pm, Drew Krause wrote [paraphrased a bit]: OK, I want to create a nested list in Lisp (always of only integers) from a text file, such that each line in the text file would be represented as a sublist in the 'imported' list. example of a file's content 3 10 2 4 1 11 18 example of programing behavior (make-list-from-text blob.txt) = ((3 10 2) (4 1) (11 18)) w_a_x_...@yahoo.com gave a ruby solution: IO.readlines(blob.txt).map{|line| line.split } augumented by Jilliam James for result to be numbers: IO.readlines(blob.txt).map{|line| line.split.map{|s| s.to_i }} Very beautiful. --- That's really the beauty of Ruby. This problem and ruby code illustrates 2 fundamental problems of lisp, namely, the cons problem, and the nested syntax pain. Both of which are practically unfixable. *Of course* Xah is wrong, as always. Who would expect anything else? In the Lisp style Clojure for example one does exactly the same as Jillian James (JJ) did in Ruby: (map #(map (fn [s] (Integer/parseInt s)) (.split % \\s)) (line-seq (reader blob.txt))) This is slightly longer, simply because the functions have longer names. Integer/parseInt vs to_i Also the function split takes a regexp, so I have to add the \\s here. I don’t know though if Jillians version also handles any kind of whitespac per line. And the last thing is, that the function reader returns a BufferedReader. So in general this is more valuable in real programs as opposed to one- line scripts. If we combine line-seq and reader into readline and apply the two other changes we would say: (map #(map (fn [s] (to_i s)) (.split %)) (readlines blob.txt)) vs IO.readlines(blob.txt).map{|line| line.split.map{|s| s.to_i }} So, obviously Xah is far away from any reality. It took him hours of his life to write up all his ideas about Lisp. Sad to see that all that time was wasted. All of it was wrong. Poor Xah :( And btw, Drew Krause is just a Lisp newbie. No Lisper would ever store data for his programs in the format 3 10 2 4 1 11 18 but instead as (3 10 2) (4 1) (11 18) And then read it back into the program with: (map read-string (line-seq (reader blob.txt))) André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: reading file to list
Xah Lee schrieb: Xah Lee wrote: • A Ruby Illustration of Lisp Problems http://xahlee.org/UnixResource_dir/writ/lisp_problems_by_ruby.html On Jan 17, 12:30 pm, André Thieme address.good.until. 2009.may...@justmail.de wrote: In the Lisp style Clojure for example one does exactly the same as Jillian James (JJ) did in Ruby: (map #(map (fn [s] (Integer/parseInt s)) (.split % \\s)) (line-seq (reader blob.txt))) Note that you have nested map. This is a problem of function chaning as i detailed. Yes, Jillian also has nested maps: IO.readlines(blob.txt).map{|line| line.split.map{|s| s.to_i }} The other problem of cons, is commonly seen. Just about every week, we see some perhaps beginning lisper asking how to do various trivial list manipulation problem, which you don't see such question or frequency in any of modern high level lang forms. You see questions about trivial problems every week in all forums about programming languages. It has nothing to do with conses. Wrong road. The frequently asked list manipulation question we see include how to append, prepend, or anything involving nested list such as partitioning, reordering sublists, getting leaves, interpretation of leaves, etc. This is caused by the cons. Yes, same with all containers in all programming languages. The clojure example you gave above, apparently inherited the irregular syntax problem. (you see the #, [], % things, which is breaks the lisp's sexp idea) My code used 8 “mysterious symbols”: ( ) # [ ] .% The Ruby version had these 7: ( ) | { } . And of course, neither in Ruby nor Clojure they break any idea. Also, all modern lisp basically all get fucked up by inheriting the cons (e.g. clojure, NewLisp, Arc lisp, Liskell). Often, they change the semantic a bit apparently as a mesaure towards solving the cons problem. (and Qi Lisp creates a huge bag of ad hoc, extremely ugly, syntax soup) Funny. What you write is an english text with words that most people can understand. You trick them into thinking that it actually makes sense what you say. It is so technical, that a random would believe it. But what you really say is about as meaningful as saying that it is impossible to write good programs in Python, because it adds whitespace to its syntax. • Fundamental Problems of Lisp http://xahlee.org/UnixResource_dir/writ/lisp_problems.html You wasted lots of your time. Or was this maybe generated by a bot? Maybe http://pdos.csail.mit.edu/scigen/ or something like that? I also found this paper that you wrote: http://apps.pdos.lcs.mit.edu/scicache/184/scimakelatex.7076.Xah+Lee.html Another crap posting of you. But a random person might be impressed. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Paul Rubin schrieb: GC also gets rid of programs. There are programs you can write in C but not in Lisp, like device drivers that poke specific machine addresses. You are talking about an ANSI Common Lisp implementation. But nothing stops a vendor to deliver its CL with libs that support the writing of device drivers. When Naughty Dog programmed games for the Play Station 2 the used Common Lisp to develop a Lisp called GOAL (Game Oriented Assembly Lisp) that was specialized for writing PS2 games. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
greg schrieb: André Thieme wrote: (aif (timeConsumingCalculation) (use it)) I think the answer is that you just wouldn't do that in Python at all. Having magic variables spring into existence in your local namespace as a side effect of calling something is just not Pythonic. (It is very Perlish, on the other hand.) The closest you might come is using the new with statement like this: with aif(timeConsumingCalculation()) as it: use(it) where the object returned by aif(x) has an __enter__ method that raises an exception which aborts the whole with statement if x is None, thus avoiding executing the body. But that's so horribly convoluted that any sane programmer would just write it out the straightforward way to begin with. Sounds like Blub to me: http://www.paulgraham.com/avg.html I will quote some parts of it: You can see that machine language is very low level. But, at least as a kind of social convention, high-level languages are often all treated as equivalent. They're not. Technically the term high-level language doesn't mean anything very definite. There's no dividing line with machine languages on one side and all the high-level languages on the other. Languages fall along a continuum [4] of abstractness, from the most powerful all the way down to machine languages, which themselves vary in power. [...] Programmers get very attached to their favorite languages, and I don't want to hurt anyone's feelings, so to explain this point I'm going to use a hypothetical language called Blub. Blub falls right in the middle of the abstractness continuum. It is not the most powerful language, but it is more powerful than Cobol or machine language. And in fact, our hypothetical Blub programmer wouldn't use either of them. Of course he wouldn't program in machine language. That's what compilers are for. And as for Cobol, he doesn't know how anyone can get anything done with it. It doesn't even have x (Blub feature of your choice). As long as our hypothetical Blub programmer is looking down the power continuum, he knows he's looking down. Languages less powerful than Blub are obviously less powerful, because they're missing some feature he's used to. But when our hypothetical Blub programmer looks in the other direction, up the power continuum, he doesn't realize he's looking up. What he sees are merely weird languages. He probably considers them about equivalent in power to Blub, but with all this other hairy stuff thrown in as well. Blub is good enough for him, because he thinks in Blub. When we switch to the point of view of a programmer using any of the languages higher up the power continuum, however, we find that he in turn looks down upon Blub. How can you get anything done in Blub? It doesn't even have y. By induction, the only programmers in a position to see all the differences in power between the various languages are those who understand the most powerful one. (This is probably what Eric Raymond meant about Lisp making you a better programmer.) You can't trust the opinions of the others, because of the Blub paradox: they're satisfied with whatever language they happen to use, because it dictates the way they think about programs. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Paul Rubin schrieb: Kirk Sluder [EMAIL PROTECTED] writes: Personally, I've always preferred use the imperative to describe basic math rather than the passive. This would seem to map better to RPN than infix. For writing down complicated, nested expressions too? That's very unusual. E.g. n! = (n/e)**n * sqrt(2*pi*n) * (1 + (1/12n)) * ... vs. the same thing in Lisp notation, and that's not even so complicated. As I said earlier: if there are three formulas in your code, then it doesn't matter too much. If you write more then use infix in Lisp. It even looks better than Python: [7x₆ + 9π³ - 6ˣ] or (if [√2 ≈ 1,41] (print Yay)) Or mathematical reasoning: (proof [∃ x∈M ∀ y∈Q : x≤y]) So what? André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
greg schrieb: Ken Tilton wrote: The reason I post macro expansions along with examples of the macro being applied is so that one can see what code would have to be written if I did not have the defskill macro to write them for me. It seems to me your brain is somewhat stuck on the use of macros. That you see it this way is normal. A BASIC programmer would tell you the same thing. He can show you solutions that don't use classes, methods or functions. Some sweet gotos and gosubs are enough. The idea is that macros save you tokens and allow you to experess in a clearer way what you want to do. But in no case one needs them to solve a programming problem. All what Kenny showed could be done without his macro. It would just be a bit more complicated and the resulting code wouldn't look good. You're looking at the expansion of your macro and assuming that you'd have to write all that code by hand if you didn't have macros. You're not thinking about alternative approaches, which could just as well be used in Lisp as well as Python, that are just as compact yet don't make use of macros. He wouldn't have to write the full expansion. With functional programming he could also solve it, but then he would need a funcall here, a lambda there. And his code would not look so understandable anymore, because it is filled up with some low level details. I will take one of the first macro examples form On Lisp. Let's say for some reason you want to analyse some numbers and do something depending on their sign. We want a function numeric if: def nif(num, pos, zero, neg): if num 0: return pos else: if num == 0: return zero else: return neg In Lisp very similar: (defun nif (num pos zero neg) (case (truncate (signum num)) (1 pos) (0 zero) (-1 neg))) Now one example Graham gives is: (mapcar #'(lambda (x) (nif x 'p 'z 'n)) '(0 2.5 -8)) which results in the list (Z P N). You can do the same thing in Python. But it gets hairier if we want to make function calls that have side effects. Let me add these three functions: (defun p () (print very positive) positive) (defun z () (print no no) zero) (defun n () (print very negative) negative) And now see what happens: CL-USER (mapcar #'(lambda (x) (nif x (p) (z) (n))) '(0 2.5 -8)) very positive no no very negative very positive no no very negative very positive no no very negative (zero positive negative) The messages were printed in each case. To stop that I need lazy evaluation: CL-USER (mapcar #'(lambda (x) (funcall (nif x #'(lambda () (p)) #'(lambda () (z)) #'(lambda () (n) '(0 2.5 -8)) no no very positive very negative (zero positive negative) I put the calls to the functions p, z and n into a function object. In some languages it would look a bit cleaner, for example Ruby. They have a single name space and don't need funcall and lambda is shorter. But still, we need to add several tokens. Maybe Haskell has built in support for that. Now with nif as a macro: (defmacro nif (expr pos zero neg) `(case (truncate (signum ,expr)) (1 ,pos) (0 ,zero) (-1 ,neg))) It is a bit more complex as the function. It has one ` and 4 ,s extra. But now we can express the problem very well: CL-USER (mapcar #'(lambda (x) (nif x (p) (z) (n))) '(0 2.5 -8)) no no very positive very negative (zero positive negative) And the first example also still works the same way. Now the expansion shows more code than we would have need to write ourself. However, now we can write code that matches much better how we think. No need for low level details like embedding the code inside of anon functions. This represents what most macros do. Save one or more lambdas and/or funcalls. One consequence is that development time gets cut down. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Paul Rubin schrieb: André Thieme [EMAIL PROTECTED] writes: def nif(num, pos, zero, neg): if num 0: return pos else: if num == 0: return zero else: return neg def nif(num, pos, zero, neg): return (neg, zero, pos)[cmp(num, 0)+1] That is a nice idea. I can do the same in Lisp, but have to do it without syntactic sugar which makes it longer, characterwise: (defun nif2 (num pos zero neg) (nth (1+ (truncate (signum num))) (list pos zero neg))) What Python has is cmp. That is doing what truncate+signum do in Lisp. So that makes the biggest difference. Another one is that Lisps signum keeps the datatype: cmp(5.3, 0) = 1 (signum 5.3) = 1.0 Or also with complex numbers [syntax #C(real, img)]: (signum #C(10 4)) = #C(0.9284767 0.37139067) Anyway, from the complexity the Lisp version is a bit better. The Python version has 11 tokens: return, tuple-reference, comma, neg, zero, pos, +, 1, cmp, num, 0 and the Lisp version has only 9: nth, 1+, truncate, signum, num, list, pos, zero, neg (I didn't count the function head, because both have the same token count). The messages were printed in each case. To stop that I need lazy evaluation: CL-USER (mapcar #'(lambda (x) (funcall (nif x #'(lambda () (p)) #'(lambda () (z)) #'(lambda () (n) '(0 2.5 -8)) in Python: def lazy_nif(num, pos, zero, neg): return (neg, zero, pos)[cmp(num, 0)+1]() # the () at the end means funcall map(lambda x: lazy_nif(x, p, z, n), (0, 2.5, -8)) We could do the same in Lisp: (defun lazy-nif (num pos zero neg) (funcall (nth (1+ (truncate (signum num))) (list pos zero neg Here the token count is 12py vs 10cl. CL-USER (mapcar #'(lambda (x) (lazy-nif2 x #'p #'z #'n)) '(0 2.5 -8)) no no very negative very positive (zero negative positive) But there is a disadvantage: lazy_nif(0, p, z, n) Traceback (most recent call last): File stdin, line 1, in ? File stdin, line 2, in lazy_nif TypeError: 'str' object is not callable I don't know how I can fix that. Maybe you could tell me. In Lisp I would just go with the macro. That works for all cases. nif is even cleaner in Haskell, if I have this right: nif x p z n | (x 0) = n | (x == 0) = z | (x 0) = p All Haskell evaluation is automatically lazy, so no lambdas etc. needed. Yes, that was what I already supposed. Do you also know how I can deactivate lazyness? André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Christophe Cavalaria schrieb: Paul Rubin wrote: André Thieme [EMAIL PROTECTED] writes: def nif(num, pos, zero, neg): if num 0: return pos else: if num == 0: return zero else: return neg def nif(num, pos, zero, neg): return (neg, zero, pos)[cmp(num, 0)+1] Since we are in one liners, let's be even smarter and do it like that : def nif(num, pos, zero, neg): return (zero, pos, neg)[cmp(num, 0)] Okay, that reduces the complexity of the Python version to that of Lisp. Now both have the same token count. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Paul Rubin schrieb: André Thieme [EMAIL PROTECTED] writes: and the Lisp version has only 9: nth, 1+, truncate, signum, num, list, pos, zero, neg Oh come on, you have to count the parentheses too. We could define hundreds of way how to count tokens. But see the program as a tree: nth / \ / \ / \ 1+ list | / | \ | / | \ truncatepos zero neg | | signum | | num And I didn't count the indentation level and \n in Python code. Why should I? They are editor commands. Anyway, token count doesn't mean much, you have to instead go by the user's cognitive effort in dealing with the prefix notation etc., How complicated ss it to say cmp(a, b) compared to a cmp b? After a few days writing Lisp code your brain specializes on that style. Arabian countries write from right to left. They seem to have no problem to use what they know. I admit that I am used to write +, -, * and / infix, because I were trained in that thinking since day 1 in school. In our example program there was only 1+ compared to .. + 1 which looks alien to untrained people. If a program uses extensive math we can get syntax for Lisp that is even more pleasant to read than Pythons: 17a + x³-x² which isn't purely a matter of token count. And if (+ 2 3) were really as easy to read as 2+3, mathematics would have been written that way all along. Mathmaticians invented prefix notation and they use it regularily. They inventey operators that wrap around their arguments, as one can see here: http://www.mathe-trainer.com/formel/?SN=t=1 Or think of indices, etc. TypeError: 'str' object is not callable I don't know how I can fix that. Maybe you could tell me. lazy_nif(0, lambda: p, lambda: z, lambda: n) Yes, that works. And that's why I wanted to make it a macro. Now you are essentially doing what I did in my first Lisp version. While this works it is farer away from what we think. (nif 0 p z n) (nif 0 #'p #'z #'n) are exactly what one thinks. For this reason if is implemented as a keyword in Python. It allows you to give code as a block instead of embedding it into a lambda or a def (which even needs a name). And we might go further (again with an easy Graham example). See this typical pattern: result = timeConsumingCalculation() if result: use(result) We need this ugly temporary variable result to refer to it. If we could use the anaphor[1] it that could make situations like these more clean. Imagine Python would have an anaphoric if, aif. Then: aif timeConsumingCalculation(): use(it) Many Lispers might have this as a macro in their toolbox after some time of coding or after reading Graham. A short three-liner in Lisp and I can really say: (aif (timeConsumingCalculation) (use it)) How would you solve this in Python? You could embed it inside a lambda and must somehow make the variable it visible in it, because in the context of aif this it gets bound to the result. All Haskell evaluation is automatically lazy, so no lambdas etc. needed. Yes, that was what I already supposed. Do you also know how I can deactivate lazyness? There's a Haskell builtin called 'seq' which forces evaluation but again I'm not sure precisely how to apply it here. I wouldn't wonder if there was an operator like seq to do that. So in some languages that support functional programming one needs to do extra work to get lazyness, while in Haskell one gets extra work if one doesn't want it. But maybe someone can correct me here. In Lisp one could build some features to get lazyness as well. [1] http://en.wikipedia.org/wiki/Anaphora_%28linguistics%29 I hope this posting was not sent two times. I just sent it but it didn't appear in my list after reloading. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Neil Cerutti schrieb: That's not a real difficulty, is it? CL-USER (mapcar #'(lambda (x) (funcall (nif x p z n))) '(0 2.5 -8)) Didn't you forget the #' before p, z and n? CL-USER (mapcar #'(lambda (x) (nif x (p) (z) (n))) '(0 2.5 -8)) no no very positive very negative (zero positive negative) And the first example also still works the same way. That's the part that Python doesn't naturally provide, and I believe, Python programmers don't usually want. Then I have the solution: they can build their own functional if. Instead of if x 10: do() something() else: foo() They can say: def blah1(): do() something() def blah2(): foo() pythonIF(x 10, # then blah1, # else blah) I personally thought the first version was the Python way. Now let's admit that nif number: pos_then: p() zero_then: z() neg_then: n() is also the Python way. With just one problem: they can't have it. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
William James schrieb: I suppose that is Ruby code. So my statement was correct when I said: In some languages it would look a bit cleaner, for example Ruby. This is because it has a minimal syntax for lambda. def p puts very positive positive end def z puts no no zero end def n puts very negative negative end def nif num, pos, zero, neg send( num0 ? pos : (num==0 ? zero : neg) ) end This code would work [0, 2.5, -8].map{|x| nif x, :p, :z, :n} See how you move away from the idea of an if. Here you need to say :p, :z, :n. That is not much better as Lisps #' ### Another way # p = proc { puts very positive positive } z = proc { puts no no zero } n = proc { puts very negative negative } def nif num, pos, zero, neg ( num0 ? pos : (num==0 ? zero : neg) ).call end [0, 2.5, -8].map{|x| nif x, p, z, n} But will this version also work this way: [0, 2.5, -8].map{|x| nif x, p, z, n} You can't express it like an if in Ruby. In Lisp it is like an IF and represents exactly what we think. IF in Lisp: (if expr (then-part) (else-part)) nif in Lisp: (nif expr (positive-part) (zero-part) (negative-part)) It looks as if it were a construct directly built into Lisp. If one wants one could even add some additional syntax, so that it looks like: (nif expr positive: (foo1) (foo2) zero: (foo3) negative: (foo4)) If you regard that idea nonsense then I suggest you to not use Rubys if-statement anymore. But instead program your own version RubyIF so that in future you have to pass all code inside blocks to your RubyIF function. If you *really* think that the Lisp savings are not worth it, then you would begin with my suggestion today. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
William James schrieb: def nif num, pos, zero, neg send( num0 ? pos : (num==0 ? zero : neg) ) end btw, your nif body is built out of 13 tokens, so more complicated than the Python version. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
greg schrieb: [EMAIL PROTECTED] wrote: Adding parentheses ... all this is a burden specific to Python. As opposed to Lisp, where all you have to do is use parentheses... oh, er... Lisp has no parens. An editor could support a mode where code is displayed in written in trees. There wouldn't be a single paren. By the way, you guys seem fixate on the parentheses of Lisp without having the experience I don't know about the other Pythonistas in this discussion, but personally I do have experience with Lisp, and I understand what you're saying. I have nothing against Lisp parentheses, I just don't agree that the Lisp way is superior to the Python way in all respects, based on my experience with both. Lisp is not superior in all respects. As soon you decide to use a language you decide against other features. Python is especially strong as a scripting language as that is the domain of it. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
William James schrieb: André Thieme wrote: William James schrieb: def nif num, pos, zero, neg send( num0 ? pos : (num==0 ? zero : neg) ) end btw, your nif body is built out of 13 tokens, so more complicated than the Python version. André -- def nif num, *args send args[ 1 + (0 = num) ] end send | | [ ] / \ / \ / \ args + / \ / \ 1 () | | = / \ / \ 0 num Okay, 9. Now it is at the complexity level of the Lisp and Python example. But how would a call to nif look like? I hope it doesn't involve an extra operator to group the args into a list or tuple. That would add more complexity to each call - so one should better have a slightly more complex nif because that exists only one time. And can this nif now handle any input values, such as strings or function objects? The = is called cmp in Python. In Lisp it is called signum. The Lisp function has in general the advantage that it keeps type information. While Pythons cmp returns either -1, 0 or 1 the Lisp version can also return -1.0 and 1.0 and also complex numbers: (signum #C(10 4)) = #C(0.9284767 0.37139067) André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
[EMAIL PROTECTED] schrieb: William James schrieb: How would you solve this in Python? You could embed it inside a lambda and must somehow make the variable it visible in it, because in the context of aif this it gets bound to the result.In Ruby: def aif val yield val if val end def complex_calc n if n % 2 == 1 n**n else nil end end aif( complex_calc( 9 ) ) {|x| puts hello, #{x}} aif( complex_calc( 8 ) ) {|x| puts hello, #{x}} --- output - hello, 387420489 Okay, so it's certainly _doable_. I think the question is more if it's usable. Regular if:s don't like that in Ruby/Python/similar, and adding such a construct would mean extending the syntax. In Lisp, all (well, almost) functions are equal, so an (if ...) would look the same like the (aif ...). I think that's the point here. Exactly that is the point. *Of course* it is doable. And what William shows us is maybe one of the best solutions in Ruby. He used advanced abstractions that made it possible. The thing with most (if not all) programming languages other than Lisp is: these abstractions are leaky. They have a low level knowledge leak. Users of aif need to know how to pass in arguments. As you see he had do embed the code that needs execution into a block (anon function) and then use this special syntax for x. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Paul Rubin schrieb: André Thieme [EMAIL PROTECTED] writes: Lisp has no parens. An editor could support a mode where code is displayed in written in trees. There wouldn't be a single paren. But there would be even more tokens, the lines going between the nodes in the trees, for example. These are painted by the editor. I also don't count the number of pixels ouf of which a letter consists as tokens. The nodes in the source tree can be one counting method which a lot of people could accept. For Python I also wouldn't count the number of spaces of indentation. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Paul Rubin schrieb: André Thieme [EMAIL PROTECTED] writes: And I didn't count the indentation level and \n in Python code. Why should I? They are editor commands. No they're part of Python syntax. A change in indent level is recognized by Python's lexical scanner as a token and you should count it. You wouldn't count the indent and \n separately though. Anyway, token count doesn't mean much, you have to instead go by the user's cognitive effort in dealing with the prefix notation etc., How complicated ss it to say cmp(a, b) compared to a cmp b? It gets worse when the expressions are nested. So instead of cmp(foo(a, b, c), bar(x, y, z)) you would prefer foo(a, b, c) cmp bar(x, y, z) ? for x in 0 range len(s): ... Maybe make single-digit functions postfix? for x in 0 range (s)len: ... Imagine Python would have an anaphoric if, aif. Then: aif timeConsumingCalculation(): use(it) Well, it's not really in the Pythonic style to add obscurity like that, but you could certainly write something like: def aif(func): it = func() if it: use(it) aif(timeConsumingCalculation) This isn't doing the same. This hardencodes the call to use() inside aif. if timeConsumingCalculation(): foo(it) bar(it) But if is already taken for the standard if. Instead we add a new keyword to Python, aif. Then we can say: aif timeConsumingCalculation(): foo(it) bar(it) You can pass anonymous functions around etc, but it will become ugly - no Pythoniast would ever do it in production code. If there was an aif built into Python we would find it every now and then. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Bruno Desthuilliers schrieb: André Thieme a écrit : Bruno Desthuilliers schrieb: (snip) Both are highly dynamic. Neither are declarative. Well, Lisp does support some declarative features in the ansi standard. If you go that way, there are declarative stuff in Python too... But neither Lisp nor Python are close to, say, SQL. While this is absolutely right one can make Lisp coming much closer, by going into the direction of, say, Prolog: http://bc.tech.coop/blog/040919.html André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Markus Triska schrieb: Ken Tilton [EMAIL PROTECTED] writes: I think all-rules-all-the-time Prolog is the poster boy for paradigm slavery. (I did try for a famous two months to use Prolog as a general-purpose programming language.) Don't expect to learn Prolog properly in so little time. To your previous question whether the ~180 lines of Lisp code in some online book constitute an industrial strength Prolog: only if the following ~180 lines of Prolog code implement an industrial strength Lisp. Hallo, you are of course right. There are some prolog implementations for Lisp that implement some parts of Prolog. To get the full thing one would of course need a big lot more of work. The idea is to get the basic constructs of Prolog available for Lisp. And with 2k LOC there are already some nice things that one can do. Those who know the paradigm of logical programming can recognize that a problem falls into this domain and then use inside of Lisp some tools that allow to express the problem in this domain specific language. If one really wants/needs Prolog then one should use it ;) The Prolog implementations are much more efficient and very stable. But often even 60% of Prolog are so expressive, that it can be a real productivity booster. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Paul Rubin schrieb: André Thieme [EMAIL PROTECTED] writes: import module module.function = memoize(module.function) Yes, I mentioned that a bit earlier in this thread (not about the during runtime thing). I also said that many macros only save some small bits of code. Your python example contains 4 tokens / brain units. The Lisp version only has 2. You shouldn't count the import statement, since you'd need the equivalent in Lisp as well. I didn't count it. 1P) module.function 2P) = 3P) memoize( 4P) module.function) vs 1L) (memoize 2L) function) I counted 1P and 4P only as one (each) although it should have been 2 for each. But it would have worked too if we didn't need the module.: function = memoize(function). Contrast the much more common a[i] = b[n] with (setf (aref a i) (aref b n)) and the attractions of Python may make more sense. Here Python and Lisp are equal, 7 tokens vs 7 tokens, but in Python one has to write less since [] are 2 chars while aref are 4, plus the setf. But from counting the brain units which I regard as an important factor they are both equal. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Bruno Desthuilliers schrieb: Mathias Panzenboeck a écrit : Mark Tarver wrote: How do you compare Python to Lisp? What specific advantages do you think that one has over the other? Note I'm not a Python person and I have no axes to grind here. This is just a question for my general education. Mark I do not know much about Lisp. What I know is: Python is a imperative, object oriented dynamic language with duck typing, Python is a dynamic multi-paradigm language which is mostly OO but has support for procedural and functional programming List s/s/p/ is a declarative, functional dynamic language - those two languages have different scopes. Lisp is a multi-paradigm language which is mostly functional but has support for procedural and OO programming. Both are highly dynamic. Neither are declarative. Well, Lisp does support some declarative features in the ansi standard. Think about :before or :after methods. And with some days of work (has already been done, so most Lispers could use it as a lib) you can get many parts of Prolog. See http://bc.tech.coop/blog/040919.html André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Steven D'Aprano schrieb: On Sat, 09 Dec 2006 14:57:08 -0500, Bill Atkins wrote: Paul Rubin http://[EMAIL PROTECTED] writes: There is just not that much boilerplate in Python code, so there's not so much need to hide it. Well, of course there is. There are always going to be patterns in the code you write that could be collapsed. Language has nothing to do with it; Lisp without macros would still be susceptible to boilerplate. Here's a concrete example: (let ((control-code (read-next-control-code connection))) (ecase control-code (+break+ (kill-connection connection) (throw :broken-by-client)) (+status+ (send-status-summary connection)) ((+noop+ +keep-alive+ ;; +X+ indicates a constant Eight lines, excluding the comment, and it doesn't handle the case where control-code is not one of +break+, +status+, +noop+ or +keep-alive+, although the ecase macro does. And how many lines of code is ecase? All of that boilerplate is handled by the macro. In Python, I would need to do something like: control_code = connection.read_next_control_code() if control_code == +break+: connection.kill() throw blah else if control_code == +status+: connection.send_status_summary() else if control_code == +noop+ || control_code == +keep_alive+: else: error CONTROL_CODE fell through conditional cascade; was not one of +BREAK+, +STATUS+, +NOOP+, +KEEP_ALIVE+ Your Python syntax is rather wonky, but that's incidental. Nine lines, including handling the case where control_code is none of the four constants. Ten if you add the pass statement that it actually needs. And it is completely self-contained, with no external functions or macros to understand. Counting source lines is not the important thing. Look at the complexity and the number of tokens. The Lisp code is easier, because it is more abstract. You are closer in saying what you want. Counting tokens: (let ((control-code (read-next-control-code connection))) 4 (ecase control-code 2 (+break+1 (kill-connection connection) 2 (throw :broken-by-client))2 (+status+ 1 (send-status-summary connection)) 2 ((+noop+ +keep-alive+ 2 == 16 control_code = connection.read_next_control_code() 4 if control_code == +break+: 4 connection.kill() 2 throw blah2 else if control_code == +status+: 4 connection.send_status_summary() 2 else if control_code == +noop+ || control_code == +keep_alive+: 8 else: 1 error CONTROL_CODE fell through conditional cascade; 2 was not one of +BREAK+, +STATUS+, +NOOP+, +KEEP_ALIVE+ == 29 plus a pass, would make 30 vs 16 Brain-units. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Steven D'Aprano schrieb: With Lisp macros, even that isn't guaranteed. Now, if Lispers would say Oh yes, macros give you great power, and with great power comes great responsibility. Be careful. Well, macros are one (big) thing that Lisp has and which many other languages don't have. Their are other things too, and some of them are in Python as well, which is a very nice scripting language. Often macros save just some bits of code. Saving one loc is not much you might say. But think about it the other way around. How would you like it to call doodleShooble() each time before you use the if statement? Of course you would not like it. The good thing about Lisp is, that you can eliminate this pattern. Apropos pattern.. most design patterns are not (very) visible in Lisp. Many of them can be abstracted away with macros+functional programming. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Bill Atkins schrieb: Bill Atkins [EMAIL PROTECTED] writes: every corner of the language? Please. Why are you so post-happy when it's quite obvious that you don't know enough about Lisp to attack it? In addition to macros that define classes or methods, a common macro is the WITH-* macro, which sets up some kind of context, runs the body inside that context, and then does some cleanup. For example, my Lisp vendor, LispWorks, provides the macro MP:WITH-LOCK : (mp:with-lock (*the-big-lock*) (do-something-atomic) (something-else) (almost-odone)) The generated first seizes a process lock called *THE-BIG-LOCK*, runs the code in the body and then releases the lock. I never have to worry that I've taken a lock without releasing it, because LispWorks has encoded that behaviour into MP:WITH-LOCK (and if they handn't, this macro is trivial to write). Now I can tell if I'm keeping a lock around too long because all the code that appears inside this WITH-LOCK is all the code that I'm locking. Further, the generated code is surrounded by an UNWIND-PROTECT, which means that if an error is raised or anything abnormal happens in the dynamic scope of the UNWIND-PROTECT, Lisp will run cleanup code as it flees back up the stack. So if there is an error in my code, it does not prevent other processes from seizing that lock, because it will be released as the error is signaled. Here is the expansion: CL-USER 7 (write (macroexpand '(mp:with-lock (*the-big-lock*) (do-something-atomic) (something-else) (almost-odone))) :pretty t :case :downcase) (let ((#:g17553 *the-big-lock*)) (when (mp:process-lock #:g17553) (unwind-protect (progn (do-something-atomic) (something-else) (almost-odone)) (mp::in-process-unlock #:g17553 Now it happens what Graham described. The blub programmer will explain that this is not needed, because he can do the same thing in blub. In Python you could write a function withLock that takes a lock and a function. Then you can say def throwAway001(): doSomethingAtomic() somethingElse() almostOdone() withLock(theBigLock, throwAway001) or maybe withLock(theBigLock, lambda (): doSomethingAtomic() somethingElse() almostOdone()) So Lisp saves you the lambda (): or def throwAway001():. That is nice I would say. Why write it if the computer could do that for you? André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Paul Rubin schrieb: Steven D'Aprano [EMAIL PROTECTED] writes: Now, if you want to tell me that, despite all the talk, Lisp coders don't actually create new syntax or mini-languages all that often, that they just use macros as functions, then the question becomes: why do you need macros then if you are just using them as functions? Why not use functions? Macros let you write what amounts to functions that don't evaluate their arguments. Think of the endless clpy wars over the ternary conditional operator. You want to write something like def ternary(test, iftrue, iffalse): if test: return iftrue else iffalse but because of side effects, you don't want a = cond(test, f(x), g(x)) to evaluate both f and g. That is trivial to do with a macro but can't be done with a function. I think you could do that with functional programming. You can protect the evaluation by encapsulating the args in a function object? def f_Args(x): return x def g_Args(x): return x and then a = cond(test, f, g, f_Args(x), g_Args(x)) if you adopt cond. But of course it is getting ugly. So a macro can free you from this extra code. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Steven D'Aprano schrieb: On Sat, 09 Dec 2006 22:41:12 -0500, Ken Tilton wrote: I know that. It was more of a rhetorical question -- Lispers are either trying to emphasis the radical nature of what you can do with macros, or understate it and make them seem just like functions. Yep, both. The first is rare. CLOS is one, my Cells (ported this summer to PyCells as part of SoC 2006) is another. The latter is the norm. If macros' advanced usage is rare, and most usage of macros could be done by functions, then maybe that explains why so many coders don't miss them. You can't do with functions what you can do with macros. Macros are just parameterized code. A template. Compare it with HTML templates html body Your name is ?py print name.getUser(loggedInUser) ?.br Welcome! /body /html The page that arrives the user does not include any template code anymore. Just plain html. Same happens with Lisp macros. After compilation (preprocessing the html template by Zope) there are no macros left. So in the end you have just some Lisp functions. So one does not *need* macros, in the sense of turing completeness. But at the same time one can meet lots of places where templates can make sense and where they are used. Even the programmers of Zope thought of them as a plus for productivity. In Lisp you don't always design one huge macro after the other, which really saves a lot of code. Many macros save one or two short lines of code. This might sound not important. But it sums up. Somewhere else I asked you to imagine how you would like it if you had to call doodleBoodle() before each if-statement to make it work. That would be plain stupid if you had to. So if you meet something in code that you use several times, then you factor that repeating block of code out into a function that takes another function which will get called in the right environment. And macros help here only to save one or two loc. But as I said, it sums up. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Fred Gilham schrieb: Paul Rubin http://[EMAIL PROTECTED] writes: André Thieme [EMAIL PROTECTED] writes: Instead of function = memoize(function) one could just say: memoize(function). In Python you'd say @memoize def function(): ... But in Lisp you'd write the function, say, Damn, I need to memoize this sucker, and evaluate (memoize 'function) and the function would be memoized. I suspect you could even do this while the program was running from something like SLIME. Basically the memoize macro changes the function cell of the symbol, so from that point all the calls to the function would be to the memoized version. You don't even need to say 'function (memoize function) would be enough. And yes, you can memoize functions while the program is running. And you don't need a tool like slime for it. Lisp already offers ways for doing that. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Steven D'Aprano schrieb: Yes. But you can't redefine 1+2 in Python, at least not without hacking the interpreter. Can you redefine (+ 1 2) in Lisp? It is possible as was pointed out. If anyone would do it, he/she would do it inside a package. Then you would write: (package:+ 1 2) So in real world programs there is no danger. In Python I could just say def list(): return 30 and won't get a warning. In Lisp I would at least have to shadow + explicitely. In Python it can't happen because + is not a function. And what do you do if you want to pass + as a HOF? André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
mystilleef schrieb: Ken Tilton wrote: Lisp has all the cool qualities you like in your pets, plus native compilation in most implementations, plus maturity and a standard, plus a better OO, plus macros, plus a dozen more small wins. Including automatic indentation. :) Better OO? You mean the one that doesn't support basic encapsulation and is retardedly cumbersome to use? There's a reason I said, I'd never use Lisp for OO not even when I'm high. Gimme Python, Eiffel or Smalltalk anyday, not the retarded add-on package bolted on CL. What do you mean with encapsulation in this context? I am looking for something that Pythons or Smalltalks OO system have which isn't in Lisps... André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Christophe schrieb: André Thieme a écrit : You don't even need to say 'function (memoize function) would be enough. And yes, you can memoize functions while the program is running. And you don't need a tool like slime for it. Lisp already offers ways for doing that. In Python while the program is running : import module module.function = memoize(module.function) Yes, I mentioned that a bit earlier in this thread (not about the during runtime thing). I also said that many macros only save some small bits of code. Your python example contains 4 tokens / brain units. The Lisp version only has 2. In the first moment one might want to say: Hey, just 10-15 more characters to type in Python. But this sums up. If someone *really* thinks this extra typing is not bad, why doesn't this person add some functions like: def foobar(): pass and call them from time to time? If a bit of extra typing is not bad one could call this function each time before one uses the built in * operator. Why not? André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Aahz schrieb: In article [EMAIL PROTECTED], Mark Tarver [EMAIL PROTECTED] wrote: I'm looking at Python and I see that the syntax would appeal to a newbie. Its clearer than ML which is a mess syntactically. But I don't see where the action is in Python. Not yet anyway. Lisp syntax is easy to learn. And giving up an order of magnitude is a high price to pay for using it over Lisp. Speaking as someone who had been programming for more than twenty years before learning Python (including a brief gander at Lisp), and also referring to many years of observations of newcomers to Python: Python's syntax also appeals to experienced programmers. I would say that your statement about Lisp syntax is wrong. Not that it is technically inaccurate, but that it completely misses the point, so much so that it is wrong to say it. One of the key goals of Python is readability, and while it is indeed easy to learn the rules for Lisp syntax, observational experience indicates that many people (perhaps even the vast majority of people) find it difficult to learn to read Lisp programs. If you ask a non-programmer to read programs he/she will have difficulties. But I guess this person would not have more problems learning than any other programming language. They are not biased because they don't know how programs look like. If you show Lisp code to people who know C or Java, Python or PHP they will not find as easily the structure. They are already used to something, and we all are creatures of habit. As for your claims about speed, they are also nonsense; I doubt one would find an order of magnitude increase of speed for production programs created by a competent Lisp programmer compared to programs created by a competent Python programmer. The Python language interpreter itself is programmed in C (biggest parts). Lisp compilers are programmed in Lisp. Both are mature production programs. Why do you think isn't the Python interpreter programmed in pure Python? Consider this: Lisp has had years of development, it has had millions of dollars thrown at it by VC firms -- and yet Python is winning over Lisp programmers. Think about it. When Lisp got so many millions it was not known how to create very good compilers. Mankind had to learn it, so these investments were needed. Today there are open source Lisps. And while they don't get millions of Dollars for development they can produce mature production code. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Ken Tilton schrieb: The last time we went thru this a Pythonista finally said, Oh, I get it. These five lines of code I have to write all the time (two setup, one func call, two cleanup) can be collapsed into one or two. The thread will be hard to miss in Google groups (two years back?) and the epiphany appears right at the end of the thread. hint Functional programming is the solution here, not Lisp. You could make that with a new function (in Python), that takes a function (and its args, don't remember the correct syntax). def foo(function, args): setup(1) setup(2) function(args) cleanup(1) cleanup(2) The nice thing in Lisp would now be to save a lambda with the macro. In Python one would fill the name space with throw away functions that get called only one time. André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Ken Tilton schrieb: André Thieme wrote: Ken Tilton schrieb: The last time we went thru this a Pythonista finally said, Oh, I get it. These five lines of code I have to write all the time (two setup, one func call, two cleanup) can be collapsed into one or two. The thread will be hard to miss in Google groups (two years back?) and the epiphany appears right at the end of the thread. hint Functional programming is the solution here, not Lisp. No, you do not understand. The Pythonista figured it out: a function would not do. What do you mean? You could make that with a new function (in Python), that takes a function (and its args, don't remember the correct syntax). def foo(function, args): setup(1) setup(2) function(args) cleanup(1) cleanup(2) The nice thing in Lisp would now be to save a lambda with the macro. In Python one would fill the name space with throw away functions that get called only one time. Omigod. Is that what you meant? You think macros are unnecessary because one could hard-code their expansions as separate functions? And that would constitute hiding the boilerplate? What happens when the boilerplate changes? game over Well, macros are unnecessary from a mathematical point of view: 0 and 1 are enough. But of course they have the potential to be a real time saver. What I want to say is: the situation you gave as an example is not the place where macros shine, because 1st class functions can take over. You could maybe give another example: how would one realize something like (memoize function) in Python? Or (defmethod name :after ..)? André -- -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
hankhero schrieb: Some clever details, like using minus to index vectors from the right. (aref hello -1) gives an error on Lisp, but the character o on Python. It would not be difficult to add this feature to Lisp. Another detail I like is that you can choose how to quote strings, in Python you can write three double-quotes to start a string that can include anything, quotes, doublequotes and newlines. You can use double-quote if you want to embed single-quotes john's or single-quote if you want to embed double-quotes 'id=2'. You could add a reader macro in Lisp that allows you to do the same. At the moment I would say that one could pretty much add most Python features to Lisp. Be it slicing, list comprehension, or, if one wants, Pythons object system. On the other hand can I see difficulties in adding macros to Python, or inventing a new object system, or adding new keywords without changing the sources of Python itself. André -- -- http://mail.python.org/mailman/listinfo/python-list