From: Christian Soltenborn
Subject: Question about local variables in function
Date: 
Message-ID: <c0h331$17ao9j$1@ID-36219.news.uni-berlin.de>
Hi,

I learned in my class that parameters of a function are call-by-value in 
lisp (or messed something up badly, I'm an exchange student :-)

Now I have the following problem: if I call the following function with 
a state as parameter, the output is fine, but the state itself changed, too.

(defun left (state)
	(let ((pos (element-index state '0))
		(cond
			((equal '0 pos) nil)
			((equal '3 pos) nil)
			((equal '6 pos) nil)
			(t (swap state (- pos 1) pos))
		)
	)
)

It's even the same if I modify the function like this:

(defun left (state)
	(let ((pos (element-index state '0))
               (tmpstate state))
		(cond
			((equal '0 pos) nil)
			((equal '3 pos) nil)
			((equal '6 pos) nil)
			(t (swap tmpstate (- pos 1) pos))
		)
	)
)

The function swap looks like this:

(defun swap (list pos1 pos2)
	(rotatef (elt list pos1) (elt list pos2))
	list
)

Can anybody give me a hint what's going on?

Thanks in advance,
Christian

From: Brian Downing
Subject: Re: Question about local variables in function
Date: 
Message-ID: <EuUWb.296996$xy6.1456544@attbi_s02>
In article <···············@ID-36219.news.uni-berlin.de>,
Christian Soltenborn  <···················@web.de> wrote:
> Now I have the following problem: if I call the following function with 
> a state as parameter, the output is fine, but the state itself changed, too.

Find a Lisp reference that talks about list structure, understand it,
and you'll see why simply binding a new name to the list will not
prevent destructive effects.

(Hint - you're only holding on to the first cell of the list!)

> (defun left (state)
> 	(let ((pos (element-index state '0))
>                (tmpstate state))
> 		(cond
> 			((equal '0 pos) nil)
> 			((equal '3 pos) nil)
> 			((equal '6 pos) nil)
> 			(t (swap tmpstate (- pos 1) pos))
> 		)
> 	)
> )

Also, please try to learn and use standard Lisp indention style.  Other
people reading your code will have an easier time, and eventually you
will as well.  C-style indentation and C-style closing braces on their
own line is very bad for Lisp.  Your editor should know what this is and
do it for you.

Compare:

(defun left (state)
  (let ((pos (element-index state '0))
	(tmpstate state))
    (cond ((equal '0 pos) nil)
	  ((equal '3 pos) nil)
	  ((equal '6 pos) nil)
	  (t (swap tmpstate (- pos 1) pos)))))

Much more concise and readable.

-bcd
-- 
*** Brian Downing <bdowning at lavos dot net> 
From: Lars Brinkhoff
Subject: Re: Question about local variables in function
Date: 
Message-ID: <85ekszh26y.fsf@junk.nocrew.org>
Brian Downing <·············@lavos.net> writes:
> Christian Soltenborn  <···················@web.de> wrote:
> > (defun left (state)
> > 	(let ((pos (element-index state '0))
> >                (tmpstate state))
> > 		(cond
> > 			((equal '0 pos) nil)
> > 			((equal '3 pos) nil)
> > 			((equal '6 pos) nil)
> > 			(t (swap tmpstate (- pos 1) pos))
> > 		)
> > 	)
> > )
> Also, please try to learn and use standard Lisp indention style.

Also, there's no need to quote numbers, i.e. you can write 3 instead
of '3 etc.

-- 
Lars Brinkhoff,         Services for Unix, Linux, GCC, HTTP
Brinkhoff Consulting    http://www.brinkhoff.se/
From: Joe Marshall
Subject: Re: Question about local variables in function
Date: 
Message-ID: <3c9fdebm.fsf@comcast.net>
Christian Soltenborn <···················@web.de> writes:

> Hi,
>
> I learned in my class that parameters of a function are call-by-value
> in lisp (or messed something up badly, I'm an exchange student :-)

They are.  Call by value means exactly this:
If I define a function 

(defun foo ()
  (let ((x 33))
    (bar x)
    (print x)))

There is *no way* that you can write the function BAR so that the
PRINT expression prints something other than 33.

> Now I have the following problem: if I call the following function
> with a state as parameter, the output is fine, but the state itself
> changed, too.

You are passing an aggregate value and modifying the contents.

-- 
~jrm
From: Jeremy Yallop
Subject: Re: Question about local variables in function
Date: 
Message-ID: <slrnc2o694.p2n.jeremy@hehe.cl.cam.ac.uk>
Joe Marshall wrote:
> Call by value means exactly this:
> If I define a function 
> 
> (defun foo ()
>   (let ((x 33))
>     (bar x)
>     (print x)))
> 
> There is *no way* that you can write the function BAR so that the
> PRINT expression prints something other than 33.

  (defun bar (x)
    (setf *print-base* 34))
From: Joe Marshall
Subject: Re: Question about local variables in function
Date: 
Message-ID: <ptcjbyuq.fsf@comcast.net>
Jeremy Yallop <······@jdyallop.freeserve.co.uk> writes:

> Joe Marshall wrote:
>> Call by value means exactly this:
>> If I define a function 
>> 
>> (defun foo ()
>>   (let ((x 33))
>>     (bar x)
>>     (print x)))
>> 
>> There is *no way* that you can write the function BAR so that the
>> PRINT expression prints something other than 33.
>
>   (defun bar (x)
>     (setf *print-base* 34))

I spoke too soon.  (there is always a wiseass)

(defun foo ()
  (let ((x 33))
    (bar x)
    (= x 33)))

There is *no way* that you can write the *function* BAR (assuming
normal bindings of DEFUN LET = and no funny stuff with X) such that
the return value of this function (assuming it returns normally) is
other than 't.

-- 
~jrm
From: Pascal Bourguignon
Subject: Re: Question about local variables in function
Date: 
Message-ID: <87lln7e9tw.fsf@thalassa.informatimago.com>
Joe Marshall <·············@comcast.net> writes:

> Jeremy Yallop <······@jdyallop.freeserve.co.uk> writes:
> 
> > Joe Marshall wrote:
> >> Call by value means exactly this:
> >> If I define a function 
> >> 
> >> (defun foo ()
> >>   (let ((x 33))
> >>     (bar x)
> >>     (print x)))
> >> 
> >> There is *no way* that you can write the function BAR so that the
> >> PRINT expression prints something other than 33.
> >
> >   (defun bar (x)
> >     (setf *print-base* 34))
> 
> I spoke too soon.  (there is always a wiseass)
> 
> (defun foo ()
>   (let ((x 33))
>     (bar x)
>     (= x 33)))
> 
> There is *no way* that you can write the *function* BAR (assuming
> normal bindings of DEFUN LET = and no funny stuff with X) such that
> the return value of this function (assuming it returns normally) is
> other than 't.

Yes, but that does not change the puzzling of beginners who can see that:

    (defun foo ()
      (let ((x (list 3 3)))
          (bar x)
          (equal x (list 3 3))))

can return t or nil depending on what's in bar:

    (defun bar (x)
        (incf (car x))
        (decf (cadr x)))

Here too, x is passed by value.   Only the value that is passed is the
first cons  (actually, a reference to  the first cons,  conses are not
copied  gratuituously)  of the  list  built in  the  let,  and a  cons
contains two references.


In  C too,  all the  parameters are  passed by  value.  That  does not
prevent the programmer to pass references (pointers):

    void getvalue(int index,int* value)
    {
        *value=42;
    /*  ^__ special syntax */
    }

    getvalue(1,&value);
    /*         ^__ special syntax */


Contrast this with pascal where you have the choice between passing by
value or by  reference, that is without needing  any special syntax at
the call site or within the procedure:

    procedure getvalue(index:integer;var value:integer);
    begin
        value=42;
    end;

    getvalue(1,value);



In lisp you can  box values into a cons or an  array or a structure or
some other compound value:

    (defun getvalue (index valref)
        (setf (car valref) 42))

    (let ((value (cons 3 nil)))
        (getvalue 1 value)
        (assert (= (car value) 42)))

Or, said  otherwise, if you have a  cons, or an array  or structure or
some  other  compound  value,  you  can  change it  in  spite  of  the
call-by-value aspect.   This is called  a destructive operation,  or a
side-effect. Also, care should be taken, because such a compound value
may be the source of the lisp program!


[12]> (defun getvalue (index valref)
        (setf (car valref) 42))
GETVALUE
[18]> (function-lambda-expression 'foo)
(LAMBDA NIL (DECLARE (SYSTEM::IN-DEFUN FOO))
 (BLOCK FOO
  (DOTIMES (I 3)
   (LET ((X '(3 4 5)))
    (IF (= (CAR X) 3) (GETVALUE 1 X) (FORMAT T "oops!~%")))))) ;
#(NIL NIL NIL NIL ((DECLARATION VALUES OPTIMIZE DECLARATION))) ;
FOO
[19]> (foo)
oops!
oops!
NIL
[20]> (function-lambda-expression 'foo)
(LAMBDA NIL (DECLARE (SYSTEM::IN-DEFUN FOO))
 (BLOCK FOO
  (DOTIMES (I 3)
   (LET ((X '(42 4 5))) ;;<<<==== OH! OH! 
    (IF (= (CAR X) 3) (GETVALUE 1 X) (FORMAT T "oops!~%")))))) ;
#(NIL NIL NIL NIL ((DECLARATION VALUES OPTIMIZE DECLARATION))) ;
FOO
[21]> 



-- 
__Pascal_Bourguignon__                     http://www.informatimago.com/
There is no worse tyranny than to force a man to pay for what he doesn't
want merely because you think it would be good for him.--Robert Heinlein
http://www.theadvocates.org/
From: Coby Beck
Subject: Re: Question about local variables in function
Date: 
Message-ID: <c0i682$oli$1@otis.netspace.net.au>
"Jeremy Yallop" <······@jdyallop.freeserve.co.uk> wrote in message
··························@hehe.cl.cam.ac.uk...
> Joe Marshall wrote:
> > Call by value means exactly this:
> > If I define a function
> >
> > (defun foo ()
> >   (let ((x 33))
> >     (bar x)
> >     (print x)))
> >
> > There is *no way* that you can write the function BAR so that the
> > PRINT expression prints something other than 33.

You are of course correct.  But:
> (defun foo ()
    (let ((x (list 33)))
      (bar x)
      x))
FOO

> (defun bar (a)
    (incf (car a)))
BAR

> (foo)
(34)

Not very helpful...

-- 
Coby Beck
(remove #\Space "coby 101 @ big pond . com")
From: Nils Gösche
Subject: Re: Question about local variables in function
Date: 
Message-ID: <lyn07nqes5.fsf@cartan.de>
"Coby Beck" <·····@mercury.bc.ca> writes:

> "Jeremy Yallop" <······@jdyallop.freeserve.co.uk> wrote in message
> ··························@hehe.cl.cam.ac.uk...
> > Joe Marshall wrote:
> > > Call by value means exactly this:
> > > If I define a function
> > >
> > > (defun foo ()
> > >   (let ((x 33))
> > >     (bar x)
> > >     (print x)))
> > >
> > > There is *no way* that you can write the function BAR so that the
> > > PRINT expression prints something other than 33.
> 
> You are of course correct.  But:
> > (defun foo ()
>     (let ((x (list 33)))
>       (bar x)
>       x))
> FOO
> 
> > (defun bar (a)
>     (incf (car a)))
> BAR
> 
> > (foo)
> (34)
> 
> Not very helpful...

If it's not helpful, why not explain it?

The point is:

(defun foo ()
  (let* ((x <whatever>)   ; x is bound to some object
         (y x))           ; y is bound to the same object
    (bar x)               ; this object is passed to BAR
    (eql x y)))           ; is x still bound to the same object as before?

will always return T (assuming BAR is a function and not a macro and
neither of X and Y are special variables or symbol macros or whatnot
and that DEFUN and LET and EQL have their normal meaning, and nobody
screwed up the readtable or the printer or the package system or is
using Perl and not Lisp or whatever else somebody might do to break
this.  Can we skip that kind of stuff for the moment?  And please
don't confuse newbies with EQ, either; thanks.).

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0
From: Coby Beck
Subject: Re: Question about local variables in function
Date: 
Message-ID: <c0kvbl$2jse$1@otis.netspace.net.au>
"Nils G�sche" <······@cartan.de> wrote in message
···················@cartan.de...
> "Coby Beck" <·····@mercury.bc.ca> writes:
>
> > "Jeremy Yallop" <······@jdyallop.freeserve.co.uk> wrote in message
> > ··························@hehe.cl.cam.ac.uk...
> > > Joe Marshall wrote:
> > > > Call by value means exactly this:
> > > > If I define a function
> > > >
> > > > (defun foo ()
> > > >   (let ((x 33))
> > > >     (bar x)
> > > >     (print x)))
> > > >
> > > > There is *no way* that you can write the function BAR so that the
> > > > PRINT expression prints something other than 33.
> >
> > You are of course correct.  But:
> > > (defun foo ()
> >     (let ((x (list 33)))
> >       (bar x)
> >       x))
> > FOO
> >
> > > (defun bar (a)
> >     (incf (car a)))
> > BAR
> >
> > > (foo)
> > (34)
> >
> > Not very helpful...
>
> If it's not helpful, why not explain it?
>

Sorry, I should have either done that or kept my mouth shut.

> The point is:
>
> (defun foo ()
>   (let* ((x <whatever>)   ; x is bound to some object
>          (y x))           ; y is bound to the same object
>     (bar x)               ; this object is passed to BAR
>     (eql x y)))           ; is x still bound to the same object as before?

This is a better way to to put it!  And now we get into the whole EQ EQL
EQUAL quagmire!  (for newbies that is, I think it is in fact all just so
Right when you do get it)

-- 
Coby Beck
(remove #\Space "coby 101 @ big pond . com")
From: Joe Marshall
Subject: Re: Question about local variables in function
Date: 
Message-ID: <n07mk1n3.fsf@comcast.net>
>> Joe Marshall wrote:
>> > Call by value means exactly this:
>> > If I define a function
>> >
>> > (defun foo ()
>> >   (let ((x 33))
>> >     (bar x)
>> >     (print x)))
>> >
>> > There is *no way* that you can write the function BAR so that the
>> > PRINT expression prints something other than 33.
>

"Coby Beck" <·····@mercury.bc.ca> writes:
> You are of course correct.  But:
>> (defun foo ()
>     (let ((x (list 33)))
>       (bar x)
>       x))
> FOO
>
>> (defun bar (a)
>     (incf (car a)))
> BAR
>
>> (foo)
> (34)
>
> Not very helpful...

That's sort of the intent!  Not that I don't want to be helpful, but I
want to illustrate that call-by-value is about the *variable*, not
about what it holds.

-- 
~jrm
From: Edi Weitz
Subject: Re: Question about local variables in function
Date: 
Message-ID: <m31xozzvio.fsf@bird.agharta.de>
On Thu, 12 Feb 2004 17:43:22 -0600, Christian Soltenborn <···················@web.de> wrote:

> I learned in my class that parameters of a function are
> call-by-value in lisp

Read this thread (all of it):

  <http://www.google.com/groups?threadm=m3n1f3mgal.fsf%40mindspring.com>

Edi.
From: Wolfhard Buß
Subject: Re: Question about local variables in function
Date: 
Message-ID: <m3isiaonxo.fsf@buss-14250.user.cis.dfn.de>
* Christian Soltenborn writes:

> (defun swap (list pos1 pos2)
> 	(rotatef (elt list pos1) (elt list pos2))
> 	list)
>
> Can anybody give me a hint what's going on?

Pauls non-consing swap is dangerous!  It affects data, accessible
through its arguments, as a side effect.  Call it nswap, and use it
with caution.

A non-destructive swap

 (defmethod swap ((list list) (pos1 integer) (pos2 integer))
   (let* ((cut (1+ (max pos1 pos2)))
          (prefix (copy-seq (subseq list 0 cut))))
     (rotatef (elt prefix pos1) (elt prefix pos2))
     (concatenate 'list prefix (subseq list cut))))

for your left function.

 (defun left (state)
   (let ((pos (element-index state 0)))
     (case pos
       ((0 3 6) nil)
       (t (swap state (1- pos) pos)))))

Hope this helps.

-- 
"Hurry if you still want to see something. Everything is vanishing."
                                       --  Paul C�zanne (1839-1906)
From: Wolfhard Buß
Subject: Re: Question about local variables in function
Date: 
Message-ID: <m3fzde6p9i.fsf@buss-14250.user.cis.dfn.de>
* I wrote:

> A non-destructive swap
>
>  (defmethod swap ((list list) (pos1 integer) (pos2 integer))
>    (let* ((cut (1+ (max pos1 pos2)))
>           (prefix (copy-seq (subseq list 0 cut))))
>      (rotatef (elt prefix pos1) (elt prefix pos2))
>      (concatenate 'list prefix (subseq list cut))))

The attentive reader wonders whether swaps behavior for eql pos1 pos2
is a bug or a feature...

-- 
"Hurry if you still want to see something. Everything is vanishing."
                                       --  Paul C�zanne (1839-1906)