Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!pacific.mps.ohio-state.edu!linac!att!cbnews!cbnewsl!davel From: davel@cbnewsl.att.com (David Loewenstern) Newsgroups: comp.lang.lisp Subject: Re: Accessing a field of a Lisp structure Message-ID: <1991Apr14.181950.21605@cbnewsl.att.com> Date: 14 Apr 91 18:19:50 GMT References: <28047A1F.44CE@ibma0.cs.uiuc.edu> <1991Apr11.215248.9075@cbnewsl.att.com> <1991Apr14.073241.23653@Think.COM> Distribution: usa Organization: AT&T Bell Labs, Whippany, NJ Lines: 129 In article <1991Apr14.073241.23653@Think.COM> barmar@think.com (Barry Margolin) writes: >In article <1991Apr11.215248.9075@cbnewsl.att.com> davel@cbnewsl.att.com (David Loewenstern) writes: >>In article <28047A1F.44CE@ibma0.cs.uiuc.edu> epstein@sunc4.cs.uiuc.edu (Milt Epstein) writes: >>>I sent a message to Barry suggesting the INTERN-FORMAT version, and he >>>pointed out a couple of things: >>> >>>1. It's better to use FIND-SYMBOL than INTERN, since the symbol (the >>>structure accessor function) should already exist. >> >>Maybe. The cost of using find-symbol is that the macro writer >>must add some error handling code, or else (access-field instance oops) >>will generate some unreadable nonsense about test-NIL being undefined. > >Both FIND-SYMBOL and INTERN will return the appropriate symbol if a valid >slot name was specified. If a nonexistent slot name was specified, INTERN >will result in an undefined function error regarding TEST-, >while FIND-SYMBOL will result in an attempt to funcall NIL. Exactly. So the version with Find-Symbol, when run, will generate a TEST-NIL error, and the version with INTERN, when run, will generate a TEST- error. Test- is of course more useful for debugging, although either method is lazier and less preferable than placing explicit error-checking code in the macro definition. > >>>2. The CASE version appeared to be much faster (he did some timing >>>test on a Symbolics). >> >>This, however, I do not believe. After all, the macro >> >>(access-field instance a) >> >>expands during compile time directly into >>(test-a instance) >> >>The function access-field *calls* test-a and so cannot possibly >>be faster than test-a alone. > >Ahh, now I see your confusion. I didn't write a macro, I wrote a function. >A macro can't be used for what the original poster wanted. He wanted a >function that takes the slot name as an argument, so that the slot can be >specified at runtime. His example was something like: Ahh, now I see your confusion. The poster I responded to wasn't the one who wanted a function. He said: >>>I would like to wite a macro 'access-field' that I can invoke >>>something like >>> >>> (access-field instance 'a) >> > >(defun prt (person slot) > (print (user-slot person slot))) > >Your macro version doesn't seem to be very useful to me. If the slot name >has to be known at compile time then it is just as easy to write the call >to the accessor directly. What's the difference between > >(access-field instance a) > >and > >(test-a instance) > >? The original post asked for something that would be > >(access-field instance 'a) > >That little quote makes a BIG difference. Since the poster specifically asked for a macro, not a function, I assumed the quote was to be considered syntactic sugar placed there for consistency with function syntax. As far as utility, I can think of a reason: unity of syntax between function and macro, coupled with a need for speed of access, as in: (defmacro access-field (struc slot) (if (OR (ATOM slot) (EQ (FIRST slot) 'QUOTE)) `(,(intern (format nil "~a-~a" 'test (IF (ATOM slot) slot (SECOND slot))) ,struc) `(access-field-function ,struc ,slot))) I have actually seen this done in a real program. Why? So tools like the following could be created: (defmacro most-recent (struc slot) `(CDAR (access-field ,struc ,slot))) (defmacro value-at-time (struc slot time) `(CDR (ASSOC ,time (access-field ,struc ,slot)))) and so forth. > >>The only way the function could be faster than the macro is if you >>are including the macroexpansion time with the execution time. > >Now that I've explained, I think you see why the CASE version is faster. >The FORMAT-INTERN version calls FORMAT and conses a string each time it is >called. > Actually, for structures with *very large* numbers of slots, format-intern is still faster, but I certainly didn't mean for format-intern to be used when the formatting was done at run time. For normally-sized structures, looking up the slot using CASE is faster, and even for huge structures, format-intern won't be any faster than a hash-table. The CASE method is a bit of a pain if the structure is still under development, however, and is no better than format-intern when the slot-to-accessor translation is to be done at compile-time. >-- >Barry Margolin, Thinking Machines Corp. > >barmar@think.com >{uunet,harvard}!think!barmar Barry, no one is questioning your understanding of Lisp structures. It appears, however, that one of us misunderstood the question. David Loewenstern AT&T Bell Laboratories 14B-253 Whippany, NJ 07981 email: davel@whutt.att.com || whutt!davel at&t: 201-386-6516