Path: utzoo!utgpu!attcan!uunet!lll-winken!lll-lcc!ames!think!barmar From: barmar@think.COM (Barry Margolin) Newsgroups: comp.lang.lisp Subject: Re: #< syntax Message-ID: <25340@think.UUCP> Date: 9 Aug 88 04:20:49 GMT References: <3387@phoenix.Princeton.EDU> <24911@think.UUCP> <3394@phoenix.Princeton.EDU> <25254@think.UUCP> <3425@phoenix.Princeton.EDU> Sender: usenet@think.UUCP Reply-To: barmar@kulla.think.com.UUCP (Barry Margolin) Distribution: na Organization: Thinking Machines Corporation, Cambridge, MA Lines: 139 In article <3425@phoenix.Princeton.EDU> eliot@phoenix.Princeton.EDU (Eliot Handelman) writes: >That's absolutely true. The difference between hash tables and procedures >is that Steels tells me how to access hash tables and doesn't indicate >how I can access lambdas. This is because of the differences in purposes of the two data types. The purpose of a hash table is to store data, so there must obviously be a way to extract that data. The purpose of a procedure is to represent an executable program, and the primitive that is necessary for this data type is APPLY. The data that is represented by a procedure is abstract, not concrete. >All that I'm saying is that I think it's contrary to the nature of lisp >to decide who's going to use it, and why, and what they're going to do with >it. My code may be very idiosyncratic, but so what? So what if I do things >in a way that earlier lisps with greater flexibilty allowed, but all of >a sudden not CL? I happen to like walking code -- what's wrong with that? CL is not trying to be fascist, it is trying to allow Lisp implementors the flexibility they need. Some Lisp implementations don't even have interpreters (they compile everything immediately), so they never store lambda-expressions in procedure objects. Code that assumes that it can access the source code, modify it, and have that do something useful will not port to such implementations. >if DISSASSEBLE exists then GRINDEF (or whatever) ought to >be made public too, if only for purely pedagogical reasons. I agree that GRINDEF should have been included. I'm surprised that it wasn't, since it was in the predecessors to CL. However, it wouldn't have solved your problem, since GRINDEF merely PRINTS the source code, it doesn't return it in some data structure that your application can get at. >I think this point is too important to overlook. Winston and Horn have their >M-LISP interpreter at the end of their book. Can you write decent lisp code >without *really* understanding how (say) the read-eval-print loop works? >Isn't there a near isomorphy between lisp implementors and lisp programmers? I don't think you really need to know more about the read-eval-print loop than what is said in CLtL. All you need to know about DEFUN, for example, is that it puts *something* in the symbol's function cell, and when that *something* is APPLYed it will execute the specified code. What that *something* looks like is not really important when writing Lisp code, especially since it is likely to be different depending on whether the function was compiled or interpreted. >To answer your question directly, I don't try to walk compiled code, >but I see that as my problem. Why is a system that can analyze what another >lisp system would do IF it were run inconceivable? I think you SHOULD be able >to analyze compiled code, too. Just as a portable assembler is an oxymoron (claimed implementations notwithstanding), so is a portable compiled code analyzer. >>One of Common Lisp's goals was to define a language that produces >>equivalent programs whether they are compiled or interpreted. > >Why, was it ever the case that compiled programs behaved differently from >interpreted? What lisp in particular? Maclisp. In interpreted code, all variables were special; in compiled code, variables were local, unless declared special. >>The >>implementations that use an special type for interpreted functions are >>actually helping you out, since the interpreter will catch an error >>that might have remained unnoticed until you tried the program >>compiled. In fact, it might not even be caught in compiled code, >>because the compiled code for SUBST might not do any type checking; >>you might just dump core or something. > >Ok, but I don't see what this has to do with #< notation. I don't see what this whole discussion has to do with NOTATION. We are talking about data types, not notation. What I said was that since you can't access the internal structure of compiled code, the interpreter is being reasonable in disallowing access to the internal structure of interpreted code, because the interpreter is expected to catch errors that might go undiagnosed in compiled code. >>Even among implementations that store interpreted definitions as lists >>in the function cell there can be much variety. On a Symbolics >>machine, DEFUN will store a list beginning with SI:DIGESTED-LAMBDA, >>and the actual lambda expression will be just one element. There is >>currently no portable way to access the interpreted definition of a >>function. > >That's true. Point is, what difference should it make what you call >the first element, LAMBDA-BLOCK, NAMED-LAMBDA, DIGESTED-LAMBDA or >whatever? Why not push for standardization? I mean, everybody has >already agreed on the lambda part, which is of no more than historical >significance, anyway. The point is that each implementation must be free to put whatever data it needs in the procedure object. It would not be right for the Common Lisp standard to specify how procedures should be represented. >>If you have programs that construct interpreted definitions and then >>want to be able to access these definitions, you should have them >>store them somewhere else in addition to (or instead of) the function >>cells of symbols. > >Of course I could do that, but it's ugly. I think what that leads to is writing >my own interpreter, with my own version of anything that does surgery, If you're writing a code walker, you essentially have to do that anyway. Even if the function cell were required to contain a lambda-expression, you couldn't depend on it containing only recognizable functions and special forms (DEFUN might have done some implementation-dependent transformations before storing it). As someone else already pointed out, there is a group in X3J13 preparing a proposal for a SOURCE-CODE function, which will return the lambda-expression of an interpreted function. Until then, your best bet when writing a code walker is to have it read the source files itself, rather than trying to extract procedures from the function cells. This is one reason why Lisp source uses the same syntax as Lisp data. >>The function cell is not a general-purpose storage location. > >A procedure is a piece of data, whether or not it has its own special >set of accessors. Besides which, I would imagine that this view >is anathema to your company's ideology, that of the identity of the processor >and memory. I'm not sure what this means. Connection Machine software is quite cognizant of the difference between processors and memory. In fact, procedures can't even be stored in CM memory (procedures are executed by a serial front-end computer, which sends commands to the CM when it wants to perform parallel operations, so you can't execute a parallel set of procedures). Barry Margolin Thinking Machines Corp. barmar@think.com {uunet,harvard}!think!barmar