On Sat, Apr 25, 2009 at 9:06 AM, Carl Banks <pavlovevide...@gmail.com> 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