From: Miguel Arroz
Subject: Evaluation order
Date: 
Message-ID: <1095460236.626591@iceman.esoterica.pt>
Hi!

  I have a question about the evaluation order of some expressions.

  Suppose I have the following:

  (make-instance 'some-class :slot1 (function1)
                             :slot2 (function1)
                             :slot3 (function1)
                             :slot4 (function1)
                             :slot5 (function1))

  Will the (function1) calls be evaluated on order (first, for slot1, 
next for slot2, etc) or is the order not specified by the language? Note 
that I do not want to know that in the XPTO compiler it works that way. 
I'm referring to the LISP specification. I know some evaluations may be 
done in parallel, if the hardware allows it (like the "let" evaluation, 
that's why there is the let*). I want to know is this one in particular 
is in parallel or serial.

  Yours

Miguel Arroz

From: Matthew Danish
Subject: Re: Evaluation order
Date: 
Message-ID: <20040917224009.GF408@mapcar.org>
On Fri, Sep 17, 2004 at 10:31:15PM +0000, Miguel Arroz wrote:
>   Will the (function1) calls be evaluated on order (first, for slot1, 
> next for slot2, etc) or is the order not specified by the language? 

MAKE-INSTANCE is a function.  The order of evaluation is specified for
the arguments to a function: left to right.

-- 
;;;; Matthew Danish -- user: mrd domain: cmu.edu
;;;; OpenPGP public key: C24B6010 on keyring.debian.org
From: ·········@random-state.net
Subject: Re: Evaluation order
Date: 
Message-ID: <cigkdu$983b6$1@midnight.cs.hut.fi>
Miguel Arroz <·····@guiamac.com> wrote:

>   Will the (function1) calls be evaluated on order (first, for slot1, 
> next for slot2, etc) 

Yes.

> I'm referring to the LISP specification. I know some evaluations may be 
> done in parallel, if the hardware allows it (like the "let" evaluation, 
> that's why there is the let*). I want to know is this one in particular 

This is not true: LET, and eg. PSETF never do paraller evaluation:
in

 (let ((x1 (form1))
       (x2 (form2))
       (x3 (form3)))
    ...)

FORM1, FORM2, and FORM3 are evaluated in strict left-to-right order: it's
the _binding_ of the results to X1, X2, and X3 that's done in "parallel".

Cheers,

 -- Nikodemus                   "Not as clumsy or random as a C++ or Java. 
                             An elegant weapon for a more civilized time."
From: Miguel Arroz
Subject: Re: Evaluation order
Date: 
Message-ID: <1095507591.758699@jubilee.esoterica.pt>
Hi!

  OK, thank you for your answer.

  Yours

Miguel Arroz
From: Alan Crowe
Subject: Re: Evaluation order
Date: 
Message-ID: <86ekkzg5nu.fsf@cawtech.freeserve.co.uk>
Miguel Arroz worries about make-instance: 

   Suppose I have the following:

   (make-instance 'some-class :slot1 (function1)
                              :slot2 (function1)
                              :slot3 (function1)
                              :slot4 (function1)
                              :slot5 (function1))

    Will the (function1) calls be evaluated on order
    (first, for slot1, next for slot2, etc) or is the order
    not specified by the language?

Make-instance is specified to be a function. Consequently
all implementations are required (3.1.2.1.2.3 Function
Forms) to evaluate all eleven arguments in left to right
order. You are probably wondering what kind of crack I'm
smoking because you think your call to make instance only
has 6 arguments, the class and 5 calls of function1. Think
again.

Here is some dangerous, sociopathic code that depends on
side effects in the function calls that chose which slot to
initialise, but which is never-the-less conforming code.

(defparameter *slots* '(a b c d))

(defun random-choice(list)
  (elt list (random (length list))))

(defun pick-next-slot(tag)
  "Select a symbol from a global list of slot names.
   Remove the symbol from the global list to
   prevent duplication"
  (let ((slot (random-choice *slots*)))
    (setf *slots* (remove slot *slots*))
    (format t "Picking slot ~A from invocation ~A~%"
	    slot tag)
    (find-symbol (symbol-name slot) 'keyword)))

(defun pick-a-class()
    (format t "Picking a class~%")
    (quote some-class))

(defun pick-a-value(range tag)
    (let ((sv (random range)))
      (format t "Call tagged ~A selects value ~A~%"
	      tag sv)
      sv))

(defclass some-class ()((a :initarg :a)
         		(b :initarg :b)
			(c :initarg :c)
			(d :initarg :d)))

(describe (make-instance
	    (pick-a-class)
	    (pick-next-slot 'one)
	    (pick-a-value 1000 'two)
	    (pick-next-slot 'three)
	    (pick-a-value 1000 'four)
	    (pick-next-slot 'five)
	    (pick-a-value 1000 'six)))
=>
Picking a class
Picking slot C from invocation ONE
Call tagged TWO selects value 337
Picking slot B from invocation THREE
Call tagged FOUR selects value 276
Picking slot D from invocation FIVE
Call tagged SIX selects value 510

#<SOME-CLASS {481ADD0D}> is an instance of class #<Standard-Class SOME-CLASS
                                                   {4802B045}>:
 The following slots have :INSTANCE allocation:
 D    510
 C    337
 B    276
 A    "unbound"
T

A consequence of this is that if your introspective AI program
has decided for itself that one of its classes needs more
slots, and added them to the class definition, it can then make
instances that initialise them, using the functional
interface to CLOS, rather than using eval. Eek!

Alan Crowe
Edinburgh
Scotland
From: Vassil Nikolov
Subject: Re: Evaluation order
Date: 
Message-ID: <lzhdpv197t.fsf@janus.vassil.nikolov.names>
Alan Crowe <····@cawtech.freeserve.co.uk> writes:

> [...]
>    (make-instance 'some-class :slot1 (function1)
>                               :slot2 (function1)
>                               :slot3 (function1)
>                               :slot4 (function1)
>                               :slot5 (function1))
> [...]
> You are probably wondering what kind of crack I'm
> smoking because you think your call to make instance only
> has 6 arguments, the class and 5 calls of function1.


  By the way, would it be terminologically appropriate to say that the
  above call has 11 arguments, but 6 actual parameters?


  ---Vassil.


-- 
Vassil Nikolov <········@poboxes.com>

Hollerith's Law of Docstrings: Everything can be summarized in 72 bytes.
From: Kalle Olavi Niemitalo
Subject: Re: Evaluation order
Date: 
Message-ID: <87oek2a7m8.fsf@Astalo.kon.iki.fi>
Vassil Nikolov <········@poboxes.com> writes:

>   By the way, would it be terminologically appropriate to say that the
>   above call has 11 arguments, but 6 actual parameters?

From the CLHS glossary: "actual parameter n. Trad. an argument."
So I don't think it'd be right.  And if you leave out the "actual",
then MAKE-INSTANCE has only two parameters: CLASS and INITARGS.
From: Vassil Nikolov
Subject: Re: Evaluation order
Date: 
Message-ID: <lzu0ttzpdz.fsf@janus.vassil.nikolov.names>
Kalle Olavi Niemitalo <···@iki.fi> writes:

> Vassil Nikolov <········@poboxes.com> writes:
>
>>   By the way, would it be terminologically appropriate to say that the
>>   above call has 11 arguments, but 6 actual parameters?
>
> From the CLHS glossary: "actual parameter n. Trad. an argument."
> So I don't think it'd be right.  And if you leave out the "actual",
> then MAKE-INSTANCE has only two parameters: CLASS and INITARGS.


  Yes, it was inappropriate for me to use MAKE-INSTANCE as an example
  for my question.  Let me reformulate it in this way:

    Consider (DEFUN F (&KEY X Y) ...), for which it can be said that F
    has two formal parameters (right?).  In (F :X 1 :Y 2), there are
    four arguments, and if "actual parameter" is just a synonym for
    "argument", then four actual parameters.  However, would it be
    appropriate (even if not feasible) to redefine the meaning of
    "actual parameter" so that one can say that in (F :X 1 :Y 2),
    there are _two_ actual parameters?  In other words, to let the
    term "argument" simply stand for any value supplied to a function,
    and let the term "actual parameter" take into account how such
    values are mapped to formal parameters.

  Note that the keyword values that identify keyword arguments are
  "first-class" arguments in Lisp, so, for example, it is possible to
  have (F (A1) (A2) (A3) (A4)) (provided, of course, that A1 and A3
  each return :X or :Y).  Off the top of my head, (at least some of
  the) other languages that allow actual parameters to be mapped to
  formal parameters by parameter name do not have this "first class"
  treatment of the names.


  ---Vassil.


-- 
Vassil Nikolov <········@poboxes.com>

Hollerith's Law of Docstrings: Everything can be summarized in 72 bytes.
From: Kalle Olavi Niemitalo
Subject: Re: Evaluation order
Date: 
Message-ID: <87llf5k11v.fsf@Astalo.kon.iki.fi>
Vassil Nikolov <········@poboxes.com> writes:

>     Consider (DEFUN F (&KEY X Y) ...)

[...]

>   Note that the keyword values that identify keyword arguments are
>   "first-class" arguments in Lisp, so, for example, it is possible to
>   have (F (A1) (A2) (A3) (A4)) (provided, of course, that A1 and A3
>   each return :X or :Y).

...or :ALLOW-OTHER-KEYS.  :-)

How many "actual parameters" would (F (A1) (A2) (A3) (A4)) have
according to the (re)definition you suggest?
Does the number depend on whether (A1) and (A3) return the same
value, so that keyword parsing ignores the result of (A4)?
Does it depend on whether F also has a &REST parameter?

I am getting the feeling that your definition would be rather
complicated and not very useful for explaining the actual
behavior of Common Lisp.
From: Vassil Nikolov
Subject: Re: Evaluation order
Date: 
Message-ID: <lzpt4gz9gh.fsf@janus.vassil.nikolov.names>
Kalle Olavi Niemitalo <···@iki.fi> writes:

> Vassil Nikolov <········@poboxes.com> writes:
>
>>     Consider (DEFUN F (&KEY X Y) ...)
>
> [...]
>
>>   Note that the keyword values that identify keyword arguments are
>>   "first-class" arguments in Lisp, so, for example, it is possible to
>>   have (F (A1) (A2) (A3) (A4)) (provided, of course, that A1 and A3
>>   each return :X or :Y).
>
> ...or :ALLOW-OTHER-KEYS.  :-)
>
> How many "actual parameters" would (F (A1) (A2) (A3) (A4)) have
> according to the (re)definition you suggest?
> Does the number depend on whether (A1) and (A3) return the same
> value, so that keyword parsing ignores the result of (A4)?


  (The remark at the end is the important one, but I will still answer
  these questions too...)


  Yes, it would depend on that---if they return the same value, there
  would be just one actual parameter according to what I was thinking.


> Does it depend on whether F also has a &REST parameter?


  That's a good question (my answer would be "guess not..."), and if
  it has both &REST and &ALLOW-OTHER-KEYS, then it depends on the way
  the formal parameter is used, but it indeed gets too complicated to
  define, as you have pointed out.


> I am getting the feeling that your definition would be rather
> complicated and not very useful for explaining the actual
> behavior of Common Lisp.


  Yes, you are right about _that_---it gets counterproductive.  Thank
  you for your comments.


  ---Vassil.


-- 
Vassil Nikolov <········@poboxes.com>

Hollerith's Law of Docstrings: Everything can be summarized in 72 bytes.
From: Alan Crowe
Subject: Re: Evaluation order
Date: 
Message-ID: <86y8j6e1e6.fsf@cawtech.freeserve.co.uk>
Vassil asks:

  By the way, would it be terminologically appropriate to say that the
  above call has 11 arguments, but 6 actual parameters?

I've seen the term "actual parameter" used in
contradistinction to "formal parameter". For example, in

(defun mult (x y)
  (* x y))

(mult (+ 2 2) (+ 5 7))

the formal parameters of mult are x and y and the actual
parameters are 4 and 12.

I was worried that I was misremembering this but a quick
google-search 

http://www.google.com/search?hl=en&ie=ISO-8859-1&q=%22formal+parameter%22+%22actual+parameter%22

turns up

http://www.javacommerce.com/tutorial/jbook/Notes/chap34/ch34_3.html
http://www.xgc.com/manuals/xgc-c66-rm/x1437.html

Conclusion: the term "actual parameter" is taken, and there are 11
of them.

I suspect that your best plan is to follow Keene's advice,
that one should write contructor functions:

(defun make-some-class (a b c d e)
  (make-instance 'some-class
	         :slot1 a
		 :slot2 b
		 :slot3 c
                 :slot4 d
                 :slot5 e))

Now the clumsiness is gone from your source code, so you do
not need terminology to describe it :-)

Alan Crowe
Edinburgh
Scotland
From: Coby Beck
Subject: Re: Evaluation order
Date: 
Message-ID: <aZm3d.86915$XP3.81848@edtnps84>
"Alan Crowe" <····@cawtech.freeserve.co.uk> wrote in message
···················@cawtech.freeserve.co.uk...
> I suspect that your best plan is to follow Keene's advice,
> that one should write contructor functions:

I don't think this is widely accepted as good advice as a default coding
style, for quite a few easily googled reasons.  It certainly has nothing to
do with the OP's concerns about evaluation order reliability.

> Now the clumsiness is gone from your source code, so you do
> not need terminology to describe it :-)

or the need for terminology! ;)

-- 
Coby Beck
(remove #\Space "coby 101 @ big pond . com")