[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Issue: PUSH-EVALUATION-ORDER



Issue: PUSH-EVALUATION-ORDER
References: CLtL pages 99 vs 270
Category: CLARIFICATION
Edit History: Jeff Peck, 15-Oct-1987, (version 1)
Problem Description:
    In the form: (PUSH (ref1) (CAR (ref2)))
It is unclear whether (ref1) should be evaluated before (ref2). 

CLtL, page 99, in a discussion of generalized variable macros, states:
 "Other macros that manipulate generalized variables include ... PUSH 
	...
  Macros that manipulate generalized variables must guarentee the "obvious"
  semantics: subforms of generalized-variable references are evaluated ...
  in exactly the same order as they appear in the *source* program."

[That is, the sub-forms of Place should be evaluated once, left to right.]

  "The expansion of these macros must consist of code that follows these
  rules or has the same effect as such code.  This is accomplished by
  introducing temporary variables bound to the subforms of the reference."
                                               â??â??â??â??â??â??â??â??â??â??â??â??â??â??â??â??â??â??â??â??â??â??â??â??â??

This paragraph and a discussion of SETF on the previous pages may also be
 interpreted as requiring that *all* argument forms of such macros should
 be evaluated once, in source order, left to right.


However, CLtL, page 270 states:
 "The effect of (PUSH Item Place) is roughly equivalent to
    (SETF Place (CONS Item Place))
  except that the latter would evaluate any subforms of Place twice
  while PUSH takes care to evaluate them only once."

   That is, the effect of the form (PUSH Item Place) is to evaluate 
(SETF Place (CONS Item Place)) but with subforms of Place only evaluated once.

    Place and Item appear in different order in the PUSH form and the
indicated equivalent SETF form.  Should the PUSH form have primacy over the
obvious SETF form with respect to the left-to-right evaluation?

  Are all subforms in a macro argument list guarenteed to be evaluated in
order, or only those subforms representing generalized variable references?



Test Case:
    (macroexpand '(push (ref1) (car (ref2))))

    (LET* ((#:G8 (REF2))
	   (#:G7 (CONS (REF1) (CAR #:G8))))
      (EXCL::.INV-CAR #:G8 #:G7)) 
    
	    ---versus---
    
    (LET* ((#:G5 (REF1))
	   (#:G4 (REF2)))
      NIL
      (SYS:RPLACA2 #:G4 (VALUES (CONS #:G5 (CAR #:G4)))))



Proposal: PUSH-EVALUATION-ORDER:REDEFINE-PUSH
    The form of PUSH is (PUSH Place Item).
Rationale:
    PUSH is basically defined in the wrong order with respect to the obvious
implementation.  Other generalized variable access functions are defined
with the Place form preceding the Value form.  Accept for the natural visual
clue that PUSH should attach Item "in front" of Place, it would be more
natural to write (PUSH Place Item) and be parallel to SETF forms.
Discusion:
   Never mind, this would break reams of existing code...


Proposal: PUSH-EVALUATION-ORDER:PLACE-FIRST
    Page 270 should be modified to read:
 "(PUSH Item Place) is equivalent to (SETF Place (CONS Item Place))
  except that the subforms of Place are evaluated only once."
	and
 "(PUSHNEW Item Place :test P) is equivalent to
  (SETF Place (ADJOIN Item Place :test P)) except that the subforms of 
  Place are evaluated only once."

Rationale:
   The wording of CLtL on page 99 does not disallow or contradict this
interpretation.  The wording of page 270 is already very close to this.



Proposal: PUSH-EVALUATION-ORDER:ITEM-FIRST
    Page 270 should be modified to read:
 "(PUSH Item Place) is generally equivalent to (SETF Place (CONS Item Place))
  except that the subforms of Place are evaluated only once, and Item
  is evaluated before Place."
	and
 "(PUSHNEW Item Place :test P) is generally equivalent to
  (SETF Place (ADJOIN Item Place :test P)) except that the subforms of 
  Place are evaluated only once, and Item is evaluated before Place."

    Page 99 should be modified to explain explicitly that *all* argument
forms of *any* macro that ever uses generalized variable references, *must*
evaluate in left to right order as appearing in the source.

    Specifically, the phase "subforms of the reference" which appears
several times should be changed to something like:
 "subforms of the [generalized-variable manipulating macro] arguments".

    Perhaps PUSH should be used as an example instead of the over worked SETF.

Rational:
    This is the unstated intention of the page 97-100 discussion of 
generalized-variable referencing macros, and indeed the intended definition
of "obvious semantics" for all macros.



Current-practice:
    PLACE-FIRST:  Lucid, Franz and Kyoto evaluate Place then Item.
    ITEM-FIRST:   Symbolics evaluates Item then Place.

Adoption Cost:
    Minimal, PUSH could simply be defined by the appropriate macro.

Cost of non-adoption:
    Obvious programs may be non-portable. Although it should be rare that
order of evaluation will effect actual operation.  Occasional programs may
get different results on Symbolics.

Benefits:
    The implementation and semantics of PUSH become obvious to all.
With ITEM-FIRST, it is obvious when macros wrapped around PUSH will
evaluate their arguments in the proper order, no exceptions need to be made.

Esthetics:
    Most folks won't notice.  For true esthetics, see REDEFINE-PUSH.


Discussion:
    David Moon (Symbolics) argues that the unstated intention of page 99
is the definition of the language, while admitting that:
  "The quoted paragraphs could be taken to restrict order of evaluation only
   of the subforms of (CAR (ref2)), not all of the subforms of the PUSH form."