Google Группы больше не поддерживают новые публикации и подписки в сети Usenet. Опубликованный ранее контент останется доступен.

argument passing with side effect

11 просмотров
Перейти к первому непрочитанному сообщению

not...@gmail.com

не прочитано,
10 нояб. 2006 г., 05:27:3710.11.2006
Hi,

I'm new to lisp and have a little question.
I have the following code :

(setf a '(blah))

(defun do-it (x)
(setf x 'it)
(print x))

(defun do-it-in (x)
(setf (car x) 'in)
(print x))

(do-it (car a)) ; print IT
(print a) ; print (BLAH)

(do-it-in a) ; print (IN)
(print a) ; print (IN)

Where it prints (BLAH) I was expecting (IT).
Could you explain the behavior or point me to a reference ?

I asked this because I was trying to write a simple lisp interpreter in
lisp.
So you might thing of 'a' in the code to be the environment to be
passed to my 'eval' function and
'do-it' the function to add a new binding in the environment. Is-it the
correct way to go ?
Or is it better to pass-and-return the environment around, maintaining
the code free of side-effects ?
In this later case, is there a common idiom in lisp to pass it around
(maybe like the state monad way of haskell) ?

Thanks a lot,
Thu

Pascal Bourguignon

не прочитано,
10 нояб. 2006 г., 05:44:4810.11.2006
not...@gmail.com writes:
> I'm new to lisp and have a little question.
> I have the following code :
>
> (setf a '(blah))

You have an error here, since you pass a to do-it-in and it sets the
car of the list, it breaks because here you have a literal list. When
you plan to modify lists, use (list 'blah) instead of (quote (blah)),
to build a new mutable list.

> (defun do-it (x)
> (setf x 'it)
> (print x))
>
> (defun do-it-in (x)
> (setf (car x) 'in)
> (print x))
>
> (do-it (car a)) ; print IT
> (print a) ; print (BLAH)
>
> (do-it-in a) ; print (IN)
> (print a) ; print (IN)
>
> Where it prints (BLAH) I was expecting (IT).
> Could you explain the behavior or point me to a reference ?

In lisp, the arguments are passed _by_ _value_.
Only some lisp values are references to some object.

(setf a 1) puts the number 1 in the memory slot named a:

+-----+
a: | 1 |
+-----+

(setf a (list 1 2 3)) puts a reference to the cons whose car is 1 in
the memory slot named a:

+-----+ +-----+-----+ +-----+-----+ +-----+-----+
a: | *--|---->| 1 | *--|-->| 2 | *--|-->| 3 | NIL |
+-----+ +-----+-----+ +-----+-----+ +-----+-----+

So, when you pass a to do-it-in, the content of the memory slot named
a is copied into the the memory slot named x:

In the first case, you get two totally independenant memory slots:

+-----+
a: | 1 |
+-----+

+-----+
x: | 1 |
+-----+


In the second case, you get two independant memory slots that happen
to point to the same lisp object:

+-----+ +-----+-----+ +-----+-----+ +-----+-----+
a: | *--|---->| 1 | *--|-->| 2 | *--|-->| 3 | NIL |
+-----+ +-----+-----+ +-----+-----+ +-----+-----+
^
+-----+ |
x: | *--|--------+
+-----+


(setf (car x) 0) would modify the CAR of the first cons cell, so you'd
get:

+-----+ +-----+-----+ +-----+-----+ +-----+-----+
a: | *--|---->| 0 | *--|-->| 2 | *--|-->| 3 | NIL |
+-----+ +-----+-----+ +-----+-----+ +-----+-----+
^
+-----+ |
x: | *--|--------+
+-----+

So a (print a) would show (0 2 3).


And (setf x 42) would just modify the memory slot named x:

+-----+ +-----+-----+ +-----+-----+ +-----+-----+
a: | *--|---->| 0 | *--|-->| 2 | *--|-->| 3 | NIL |
+-----+ +-----+-----+ +-----+-----+ +-----+-----+

+-----+
x: | 42 |
+-----+

and leave the memory slot named a unchanged.


--
__Pascal Bourguignon__ http://www.informatimago.com/

"You question the worthiness of my code? I should kill you where you
stand!"

not...@gmail.com

не прочитано,
10 нояб. 2006 г., 05:58:5810.11.2006
thanks Pascal !

(and what about the second part of the question ?)
Thu

On Nov 10, 11:44 am, Pascal Bourguignon <p...@informatimago.com> wrote:
> not...@gmail.com writes:
> > I'm new to lisp and have a little question.
> > I have the following code :
>

> > (setf a '(blah))You have an error here, since you pass a to do-it-in and it sets the


> car of the list, it breaks because here you have a literal list. When
> you plan to modify lists, use (list 'blah) instead of (quote (blah)),
> to build a new mutable list.
>
>
>
> > (defun do-it (x)
> > (setf x 'it)
> > (print x))
>
> > (defun do-it-in (x)
> > (setf (car x) 'in)
> > (print x))
>
> > (do-it (car a)) ; print IT
> > (print a) ; print (BLAH)
>
> > (do-it-in a) ; print (IN)
> > (print a) ; print (IN)
>
> > Where it prints (BLAH) I was expecting (IT).

> > Could you explain the behavior or point me to a reference ?In lisp, the arguments are passed _by_ _value_.

Pascal Bourguignon

не прочитано,
10 нояб. 2006 г., 06:06:3810.11.2006
not...@gmail.com writes:
> (and what about the second part of the question ?)

It's as you want, and it depends whether you're doing a toy or a real system.

Well, given that you use Common Lisp instead of scheme, perhaps you're
doing a real system, then you can handle state.

--
__Pascal Bourguignon__ http://www.informatimago.com/

The rule for today:
Touch my tail, I shred your hand.
New rule tomorrow.

not...@gmail.com

не прочитано,
10 нояб. 2006 г., 06:19:0810.11.2006
Thank you,
Thu

On Nov 10, 12:06 pm, Pascal Bourguignon <p...@informatimago.com> wrote:
> not...@gmail.com writes:

> > (and what about the second part of the question ?)It's as you want, and it depends whether you're doing a toy or a real system.

0 новых сообщений