From: ···@frogfly.org
Subject: literal array question
Date: 
Message-ID: <a7490f5a-a34a-41f2-81a9-439fc1be5802@n58g2000hsf.googlegroups.com>
Hi,

Can someone explain why TESTIT below doesn't return #S(FOO :X #(1))
every
time I call it, whereas TESTIT2 returns #(1) each time? It seems like
in the
first case the same object in memory is updated each time, where in
the second
case a different array is updated. This must be related to the use of
the
literal array, but why aren't the two cases the same?

(defstruct foo x)

(defun testit ()
  (let ((bar (make-foo :x #(0))))
    (setf (svref  (foo-x bar) 0)
          (1+ (svref (foo-x bar) 0)))
    bar))

(defun testit2 ()
  (let ((x #(0)))
    (setf (svref x 0)
          (1+ (svref x 0)))
    x))

* (testit)
#S(FOO :X #(1))
* (testit)
#S(FOO :X #(2))
* (testit2)
#(1)
* (testit2)
#(1)
*

Thanks,

Dan
--
Dan Becker

From: ···········@yahoo.com
Subject: Re: literal array question
Date: 
Message-ID: <61cc85eb-c380-45db-9d56-aa8f6c347ae1@s8g2000prg.googlegroups.com>
In both cases you are modifying something defined
using a literal.  This behavior is not specified,
and may vary between implementations.  Don't do it.

(In fact, in clisp 5.1, testit and testit2 both
 behave like you say testit behaves.)

If you look at the disassembly, you will see that
you are modifying your function on each call. Try:

(disassemble 'testit)
(testit)
(disassemble 'testit)
(testit)
(disassemble 'testit)


Use the appropriate make- function instead:

(defstruct foo x)

(defun testit ()
  (let ((bar (make-foo :x (make-array 1 :initial-element 0))))
    (setf (svref  (foo-x bar) 0)
          (1+ (svref (foo-x bar) 0)))
    bar))

(defun testit2 ()
  (let ((x (make-array 1 :initial-element 0)))
    (setf (svref x 0)
          (1+ (svref x 0)))
    x))

-f
From: Ken Tilton
Subject: Re: literal array question
Date: 
Message-ID: <47f6f9c9$0$15194$607ed4bc@cv.net>
···········@yahoo.com wrote:
> In both cases you are modifying something defined
> using a literal.  This behavior is not specified,
> and may vary between implementations.  Don't do it.
> 
> (In fact, in clisp 5.1, testit and testit2 both
>  behave like you say testit behaves.)
> 
> If you look at the disassembly, you will see that
> you are modifying your function on each call. Try:
> 
> (disassemble 'testit)
> (testit)
> (disassemble 'testit)
> (testit)
> (disassemble 'testit)
> 
> 
> Use the appropriate make- function instead:

Right. For quick hacks something like (copy-seq #(0)) will work, and 
there are copy-list and copy-tree as well.

kt

-- 
http://smuglispweeny.blogspot.com/
http://www.theoryyalgebra.com/

"In the morning, hear the Way;
  in the evening, die content!"
                     -- Confucius
From: ···@frogfly.org
Subject: Re: literal array question
Date: 
Message-ID: <2a58f5ef-2e6c-44d7-9069-a491c4560d9f@m73g2000hsh.googlegroups.com>
On Apr 4, 5:18 pm, ···········@yahoo.com wrote:
> If you look at the disassembly, you will see that
> you are modifying your function on each call. Try:
>
> (disassemble 'testit)
> (testit)
> (disassemble 'testit)
> (testit)
> (disassemble 'testit)

Interesting! The only change in output is in single line.

From:

;      05D:       8B3D1CA09A0A     MOV EDI, [#xA9AA01C]       ; #(0)

to:

;      05D:       8B3D1CA09A0A     MOV EDI, [#xA9AA01C]       ; #(1)

I would have guessed that the the ; #(0) and ; #(1) is just a comment.
Is it telling me what is located at the address [#xA9AA01C] ? It's
been 20+ years since I did any assembly language, and that wasn't x86!

Dan
--
Dan Becker
From: ···@frogfly.org
Subject: Re: literal array question
Date: 
Message-ID: <8502bfd7-5e87-4745-80ba-82ba27cfa2bc@n58g2000hsf.googlegroups.com>
Thanks, guys! This code is just setting up data for test functions, so
I think that either (copy-seq #(...)) or (make-array m :initial-
contents #(...)) is what I want for my purposes.

Dan
--
Dan Becker
From: Thomas A. Russ
Subject: Re: literal array question
Date: 
Message-ID: <ymi3apunb94.fsf@blackcat.isi.edu>
···@frogfly.org writes:

> Hi,
> 
> Can someone explain why TESTIT below doesn't return #S(FOO :X #(1))
> every
> time I call it, whereas TESTIT2 returns #(1) each time? It seems like
> in the
> first case the same object in memory is updated each time, where in
> the second
> case a different array is updated. This must be related to the use of
> the
> literal array, but why aren't the two cases the same?

Which implementation are you using?  A quick test with ACL 6.2 has them
both producing the same result, regardles of whether I use the
interpreter or the compiler.

> (defstruct foo x)
> 
> (defun testit ()
>   (let ((bar (make-foo :x #(0))))
>     (setf (svref  (foo-x bar) 0)
>           (1+ (svref (foo-x bar) 0)))
>     bar))
> 
> (defun testit2 ()
>   (let ((x #(0)))
>     (setf (svref x 0)
>           (1+ (svref x 0)))
>     x))
> 
> * (testit)
> #S(FOO :X #(1))
> * (testit)
> #S(FOO :X #(2))
> * (testit2)
> #(1)
> * (testit2)
> #(1)
> *

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Juho Snellman
Subject: Re: literal array question
Date: 
Message-ID: <87od8ienfp.fsf@vasara.proghammer.com>
···@frogfly.org writes:

> Hi,
> 
> Can someone explain why TESTIT below doesn't return #S(FOO :X #(1))
> every time I call it, whereas TESTIT2 returns #(1) each time? It
> seems like in the first case the same object in memory is updated
> each time, where in the second case a different array is
> updated. 

In both cases the same object in memory is updated each time. It's
just that in the latter example it's always being updated with the
same value, since the compiler has done constant propagation on the
(valid) assumption that conforming code will not be modifying #(0).
So no matter what X actually contains, (1+ (svref x 0))) is evaluating
to 1.

In the former example the compiler isn't smart enough to do a similar
analysis.

-- 
Juho Snellman