Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!seismo!rochester!rutgers!sri-spam!mordor!lll-tis!ptsfa!ihnp4!inuxc!iuvax!iucs!wagle From: wagle@iucs.cs.indiana.edu Newsgroups: comp.lang.lisp Subject: Re: EQ and EQUAL (Warning: *TOO LON Message-ID: <122500001@iucs> Date: Tue, 21-Jul-87 13:33:00 EDT Article-I.D.: iucs.122500001 Posted: Tue Jul 21 13:33:00 1987 Date-Received: Fri, 24-Jul-87 06:06:03 EDT References: <6638@reed.UUCP> Organization: Indiana University CSCI, Bloomington Lines: 79 Nf-ID: #R:reed.UUCP:-663800:iucs:122500001:000:4684 Nf-From: iucs.cs.indiana.edu!wagle Jul 21 12:33:00 1987 I view two objects that are otherwise EQUAL, but not EQ as having different "timestamps". The two objects look the same, but they are different because two different place/time's created them. Hash-tables on symbols and the like add some texture to this model by allowing two different creation place/time's to point to the same object (this is the case for symbols in particular, often subsets of the numbers, etc), which is useful only if done in a predictable (easy to understand) way. Conceptually, these pointers often act as keys for various searches (MEMQ, ASSQ, or homebrew tree searches). Also, since when one is destructively modifying a tree (copying entire trees to modify one piece can sometimes be (1) prohibitly time-expensive (2) eats cons cells and causes the garbage collector to be called more often and (3) isn't necessarily more understandable, and often requires more code to support) one's invariants have a lot of EQ's of subtrees in them. Having a close correspondance between one's invariants and the actual code being written makes life more pleasant, easier, and the code easier to read and understand. While appealing intuitively, your concept of efficiency is horrifying. Roughly, your MEMQ search is order N, while the equivalent MEMBER search (for the example given) is order N squared (roughly, I said). For the small N in your examples, N squared minus N isn't very large and IS negligible. But what about large N? How about N = 1000? 1000000? Just eight times slower means what could have taken 1 hour now takes 8 hours! Try using a 300 BAUD terminal and a 9600 BAUD terminal to print a long file. What takes a minute on the 9600 BAUD terminal takes over half an hour on the 300 BAUD terminal. Even small factors can add up. What you've done by removing EQ is to remove an opportunity for writing more efficient programs, WITHOUT REPLACING IT WITH SOMETHING EQUIVALENT OR BETTER! *THIS* is why people mutter and flame about your LISP being a "toy" language or "fundamentally brain damaged". You've shut out whole classes of large programs without providing any alternative. Now, I don't have an alternative. I think the equivalence classes introduced by pointers on objects by creation times and hash-tables is an essential aspect of LISP-like languages. My programming style is such that correctness is natural, obvious, and automatic once you understand the paradigm -- I have never had problems with objects not being EQ when they should or EQ when they shouldn't be (nor have I had to think about it much). I don't even think I've used EQUAL in a long time. Your challenge is to change my mind by providing a faster or a equal but more elegant alternative. You can't change my mind by taking it away, for I simply won't use your language. By the way, you're stuck with von Neumann architectures for the next decade at least. I realize my pointer semantics are ugly and unneccessary on certain non-standard architectures where efficient alternatives exist. In the meantime, my pointer semantics are explicit in my programs because I haven't yet built optimizing compilers that understand it well enough to allow it to be implicit (and possibly non-existant on appropriate architectures). I'm trying though. - - - - - - - - - - - - - - - - - - - - - - - - - - If you want to bend your mind thinking about other things, consider the idea of HASH-CONS. HASH-CONS on a particular pair of values always returns the same cons cell. What does this allow you to do? What problems does it solve? What problems does it create? Should you be able to RPLACA and RPLACD a cell cell produced by HASH-CONS? But thats trivia (and possibly bogus). If you are really concerned about good language design for LISP, look into SCHEME where you have lexical scoping for identifiers, first class functions (can be passed as arguments as well as returned as values), and many other goodies. Other functional languages (like ML, f'instance) are worth looking into. Here you are talking major overhaul of the entire language, not nit picking certain aspects. Like the man said, its good that you are thinking about these things, but don't get bogged down. Your goal as a language designer should be to allow the programmer to do what he wants, but to give him the best, cleanest, and simplest tools for doing that. You might change HOW he does what he wants, but never WHAT he wants. If you start trying to dictate what he wants to do, you've just murdered your language, because the programmer's just going to get pissed off, and go to a more pleasant language at his first opportunity.