home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #19 / NN_1992_19.iso / spool / comp / lang / lisp / 2351 < prev    next >
Encoding:
Text File  |  1992-09-01  |  4.1 KB  |  109 lines

  1. Path: sparky!uunet!mcsun!uknet!edcastle!aiai!jeff
  2. From: jeff@aiai.ed.ac.uk (Jeff Dalton)
  3. Newsgroups: comp.lang.lisp
  4. Subject: Re: static, a.k.a. eval-once
  5. Message-ID: <7412@skye.ed.ac.uk>
  6. Date: 1 Sep 92 14:08:35 GMT
  7. References: <7399@skye.ed.ac.uk> <17u2ikINNs6g@early-bird.think.com>
  8. Sender: news@aiai.ed.ac.uk
  9. Organization: AIAI, University of Edinburgh, Scotland
  10. Lines: 97
  11.  
  12. In article <17u2ikINNs6g@early-bird.think.com> barmar@think.com (Barry Margolin) writes:
  13. >In article <7399@skye.ed.ac.uk> jeff@aiai.ed.ac.uk (Jeff Dalton) writes:
  14. >>About 4 years ago, I wrote an EVAL-ONCE macro.  It appears, with
  15. >>an explanation below.  It has been claimed that my macro isn't
  16. >>portable because the behavior of gensyms isn't sufficiently
  17. >>restricted when compile and load is involved.  What I want to
  18. >>know is:
  19. >>
  20. >>  1. Is there a problem with using GENSYM this way?
  21. >
  22. >I think it should work.  While the compiler has to arrange for all
  23. >references to a particular gensym within a binary file to be the object,
  24. >similarly named gensyms in different binary files should refer to different
  25. >instances.
  26. >
  27. >BTW, I assume you realize that V should be a gensym, i.e. it should be:
  28.  
  29. Yes.  I'm not sure how I could have missed that.
  30.  
  31. >I think your version can be simplified a bit.  The expansion doesn't need a
  32. >LET binding:
  33. >
  34. >(defmacro eval-once (form)
  35. >  (let ((var (gensym)))
  36. >    `(if (boundp ',var)
  37. >     (symbol-value ',var)
  38. >     (set ',var ,form))))
  39.  
  40. Both this and the V problem were fixed in the "#+maybe" version:
  41.  
  42. #+maybe
  43. (defmacro eval-once (form)
  44.   (let ((v (gensym)))
  45.     `(locally (declare (special ,v))
  46.        (if (boundp ',v)
  47.            ,v
  48.          (setq ,v ,form)))))
  49.  
  50. I suspect (it was years ago) that what happened was that I started
  51. with something like your version, modified it (carelessly) to get
  52. around a bug in KCL, and then wrote the "#+maybe" version w/o realizing
  53. that it fixed the bug involving V.
  54.  
  55. The bug in KCL was that if a gensym appeared more than once _as data_
  56. (eg, as a quoted symbol in two different places), they would end up as
  57. separate symbols after a compile/load.  (This bug has now been fixed,
  58. I believe.)  However, the "#+maybe" has the problem that the uses
  59. of comma-V as a variable and as data have to line up, which wouldn't have
  60. worked then in KCL (I suspect).
  61.  
  62. >This looks suspiciously like the stuff we were discussing a few months ago,
  63. >where you wanted the ability to have modifiable literals in your program.
  64. >If that were allowed, you could do:
  65. >
  66. >(defstruct eval-once
  67. >  (done nil)
  68. >  value)
  69. >
  70. >(defmacro eval-once (form)
  71. >  (let ((struct (make-eval-once)))
  72. >    `(if (eval-once-done ',struct)
  73. >      (eval-once-value ',struct)
  74. >      (setf (eval-once-done ',struct) t
  75. >        (eval-once-value ',struct) ,form)))))
  76.  
  77. Well, I do want to have _some_ way to do this EVAL-ONCE trick.
  78.  
  79. You're right to suspect that this is connected to our earlier
  80. discussion.  I first brought up the static/eval-once issue on one of
  81. the Common Lisp mailing lists shortly after I'd written my macro (ie,
  82. some years back).  If I recall correctly, what was said then was that
  83. gensyms weren't reliable enough but that LOAD-TIME-VALUE might do it
  84. (somehow).  So I've had it in mind to figure out, sooner or later,
  85. whether LOAD-TIME-VALUE did help.  Various things remind me of this --
  86. such things as the discussion about modifying constants and (now) the
  87. public review of the dpANS.  (The latter one works by making me try
  88. to remember the things I was going to raise during public review,
  89. which leads me to remember other things too.)
  90.  
  91. Anyway, modifying a quoted structure looks like one way to do
  92. eval-once, and LOAD-TIME-VALUE looks like it might help either by
  93. giving you a modifiable object (that isn't quoted) at load time or by
  94. letting you modify a quoted object (because you use the 2nd argument
  95. to LOAD-TIME-VALUE to _say_ it's modifiable.  So, using the struct
  96. you defined, we might try:
  97.  
  98. (defmacro eval-once (form)
  99.   (let ((v (gensym)))
  100.     `(let ((,v (load-time-value (make-eval-once))))
  101.        (if (eval-once-done ,v)
  102.            (eval-once-value ,v)
  103.          (setf (eval-once-done ,v) t
  104.                (eval-once-value ,v) ,form)))))
  105.  
  106. But that's not enough in interpreted code.
  107.  
  108. -- jd
  109.