From: Ari Krupnik
Subject: Multiple evaluation
Date: 
Message-ID: <863alxq3fh.fsf@deb.lib.aero>
This is not a question about preventing accidental multiple evaluation
in macros, but rather about forcing multiple evaluation in functions.

Let's say I want to create a list of 5 random numbers like this:

(make-list 5 :initial-element (random 1.0))

This gives me a list of 5 identical numbers, because (random 1.0) is
only evaluated once before being passed to make-list. Is there away
around this?


Ari.

-- 
Elections only count as free and trials as fair if you can lose money
betting on the outcome.

From: Zach Beane
Subject: Re: Multiple evaluation
Date: 
Message-ID: <m3ej5hg90k.fsf@unnamed.xach.com>
Ari Krupnik <···@lib.aero> writes:

> This is not a question about preventing accidental multiple evaluation
> in macros, but rather about forcing multiple evaluation in functions.
>
> Let's say I want to create a list of 5 random numbers like this:
>
> (make-list 5 :initial-element (random 1.0))
>
> This gives me a list of 5 identical numbers, because (random 1.0) is
> only evaluated once before being passed to make-list. Is there away
> around this?

I don't really think that's behavior to work "around", since it's
working as it should. There are other ways to achieve what you want,
though. For example:

  (mapcar #'random (make-list 5 :initial-element 1.0))

Zach
From: Pascal J. Bourguignon
Subject: Re: Multiple evaluation
Date: 
Message-ID: <87ljzp97pp.fsf@hubble.informatimago.com>
Zach Beane <····@xach.com> writes:

> Ari Krupnik <···@lib.aero> writes:
>
>> This is not a question about preventing accidental multiple evaluation
>> in macros, but rather about forcing multiple evaluation in functions.
>>
>> Let's say I want to create a list of 5 random numbers like this:
>>
>> (make-list 5 :initial-element (random 1.0))
>>
>> This gives me a list of 5 identical numbers, because (random 1.0) is
>> only evaluated once before being passed to make-list. Is there away
>> around this?
>
> I don't really think that's behavior to work "around", since it's
> working as it should. There are other ways to achieve what you want,
> though. For example:
>
>   (mapcar #'random (make-list 5 :initial-element 1.0))

Consing O(2N)...

(map-into (make-list 5) (lambda () (random 1.0))) ; consing O(N).


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

CONSUMER NOTICE: Because of the "uncertainty principle," it is
impossible for the consumer to simultaneously know both the precise
location and velocity of this product.
From: Ari Krupnik
Subject: Re: Multiple evaluation
Date: 
Message-ID: <86y73poliw.fsf@deb.lib.aero>
···@informatimago.com (Pascal J. Bourguignon) writes:

> Zach Beane <····@xach.com> writes:
>
>> Ari Krupnik <···@lib.aero> writes:
>>
>>> (make-list 5 :initial-element (random 1.0))
>>
>>   (mapcar #'random (make-list 5 :initial-element 1.0))
>
> Consing O(2N)...
>
> (map-into (make-list 5) (lambda () (random 1.0))) ; consing O(N).

But it still iterates twice, just doesn't create extra garbage, right?

I think map-into does the same as what I'd come up, but is cleaner; I
didn't know about map-into (I did feel weird about using rplaca):

(mapl #'(lambda (sublist)
     (rplaca sublist (random 1.0))) (make-list 5))

Now that I read about map-into, why is it defined to take a sequence
as a first argument, and function as second, unlike other map*
functions?

Ari.

-- 
Elections only count as free and trials as fair if you can lose money
betting on the outcome.
From: John Thingstad
Subject: Re: Multiple evaluation
Date: 
Message-ID: <op.ueu4stlbut4oq5@pandora.alfanett.no>
P� Fri, 25 Jul 2008 20:40:07 +0200, skrev Ari Krupnik <···@lib.aero>:

>
> (mapl #'(lambda (sublist)
>      (rplaca sublist (random 1.0))) (make-list 5))
>
> Now that I read about map-into, why is it defined to take a sequence
> as a first argument, and function as second, unlike other map*
> functions?

Well if you don't like rplaca you could always write (setf (car sublist)  
(random 1.0)).

--------------
John Thingstad
From: Rob Warnock
Subject: Re: Multiple evaluation
Date: 
Message-ID: <8dydnZeQNo6NDRfVnZ2dnUVZ_vninZ2d@speakeasy.net>
Ari Krupnik  <···@lib.aero> wrote:
+---------------
| ···@informatimago.com (Pascal J. Bourguignon) writes:
| > (map-into (make-list 5) (lambda () (random 1.0))) ; consing O(N).
| 
| But it still iterates twice, just doesn't create extra garbage, right?
+---------------

No, it iterates *once* only!

Hint: Look at the (MAP-INTO A #'GENSYM) example in the CLHS.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Pascal J. Bourguignon
Subject: Re: Multiple evaluation
Date: 
Message-ID: <87abg589fa.fsf@hubble.informatimago.com>
····@rpw3.org (Rob Warnock) writes:

> Ari Krupnik  <···@lib.aero> wrote:
> +---------------
> | ···@informatimago.com (Pascal J. Bourguignon) writes:
> | > (map-into (make-list 5) (lambda () (random 1.0))) ; consing O(N).
> | 
> | But it still iterates twice, just doesn't create extra garbage, right?
> +---------------
>
> No, it iterates *once* only!
>
> Hint: Look at the (MAP-INTO A #'GENSYM) example in the CLHS.

MAP-INTO loops once, and MAKE-LIST too.  But I already gave the
solution that LOOPs only once.

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

ADVISORY: There is an extremely small but nonzero chance that,
through a process known as "tunneling," this product may
spontaneously disappear from its present location and reappear at
any random place in the universe, including your neighbor's
domicile. The manufacturer will not be responsible for any damages
or inconveniences that may result.
From: Rob Warnock
Subject: Re: Multiple evaluation
Date: 
Message-ID: <r8-dnZYl8u8irBbVnZ2dnUVZ_sjinZ2d@speakeasy.net>
Pascal J. Bourguignon <···@informatimago.com> wrote:
+---------------
| ····@rpw3.org (Rob Warnock) writes:
| > Ari Krupnik  <···@lib.aero> wrote:
| > +---------------
| > | ···@informatimago.com (Pascal J. Bourguignon) writes:
| > | > (map-into (make-list 5) (lambda () (random 1.0))) ; consing O(N).
| > | 
| > | But it still iterates twice, just doesn't create extra garbage, right?
| > +---------------
| >
| > No, it iterates *once* only!
| > Hint: Look at the (MAP-INTO A #'GENSYM) example in the CLHS.
| 
| MAP-INTO loops once, and MAKE-LIST too.
+---------------

*Yikes!* Sorry, you're right. Somehow I was reading the latter
as MAKE-ARRAY, which doesn't necessarily need to "loop" per se.

[Though since any sane CL:MAKE-ARRAY will initialize the block
it allocates with *something*, I suppose one could claim that
MAKE-ARRAY has to implicitly "loop", too. Unless you have a
compiler macro for MAP-INTO that notices the whole sequence
is being written and and transforms the MAKE-ARRAY into a
SYS::MAKE-ARRAY/NO-INIT or something...]

+---------------
| But I already gave the solution that LOOPs only once.
+---------------

Yes, well, I like LOOP, too.  ;-}  ;-}


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Daniel Janus
Subject: Re: Multiple evaluation
Date: 
Message-ID: <slrng8k7jq.qpd.przesunmalpe@students.mimuw.edu.pl>
Dnia 25.07.2008 Pascal J. Bourguignon <···@informatimago.com> napisa�/a:

> Zach Beane <····@xach.com> writes:
>
>> Ari Krupnik <···@lib.aero> writes:
>>
>>> This is not a question about preventing accidental multiple evaluation
>>> in macros, but rather about forcing multiple evaluation in functions.
>>>
>>> Let's say I want to create a list of 5 random numbers like this:
>>>
>>> (make-list 5 :initial-element (random 1.0))
>>>
>>> This gives me a list of 5 identical numbers, because (random 1.0) is
>>> only evaluated once before being passed to make-list. Is there away
>>> around this?
>>
>> I don't really think that's behavior to work "around", since it's
>> working as it should. There are other ways to achieve what you want,
>> though. For example:
>>
>>   (mapcar #'random (make-list 5 :initial-element 1.0))
>
> Consing O(2N)...

Which is exactly the same set as O(N), since the O notation (Theta notation
would be more precise) ``eats'' constant factors.  Saying that it conses
twice as more as your version would be more precise.

> (map-into (make-list 5) (lambda () (random 1.0))) ; consing O(N).

Just my O(1) cents ;-)

-- 
Daniel 'Nathell' Janus, ······@nathell.korpus.pl, http://korpus.pl/~nathell
M� �laim an t-airgead is m� bhronnaim an t-�r --
�, cad � sin do'n t� sin nach mbaineann sin d�?
   -- Clannad
From: Joost Diepenmaat
Subject: Re: Multiple evaluation
Date: 
Message-ID: <874p6dc1f8.fsf@zeekat.nl>
Ari Krupnik <···@lib.aero> writes:

> This is not a question about preventing accidental multiple evaluation
> in macros, but rather about forcing multiple evaluation in functions.
>
> Let's say I want to create a list of 5 random numbers like this:
>
> (make-list 5 :initial-element (random 1.0))
>
> This gives me a list of 5 identical numbers, because (random 1.0) is
> only evaluated once before being passed to make-list. Is there away
> around this?

A single argument passed to a single function call will always be
evaluated only once.

The problem isn't exactly that (random 1.0) is only evaluated once
(all function call arguments are), it's that make-list is explictly
designed to set every element to the same value.

If you want different behaviour, you'd have to create your own
implementation of make-list, possibly as a macro, or as a function
that takes a "generator" function as an argument. Or use

(list (random 1.0) (random 1.0) (random 1.0) (random 1.0) (random
1.0))

-- 
Joost Diepenmaat | blog: http://joost.zeekat.nl/ | work: http://zeekat.nl/
From: Pascal J. Bourguignon
Subject: Re: Multiple evaluation
Date: 
Message-ID: <87sktx97wm.fsf@hubble.informatimago.com>
Ari Krupnik <···@lib.aero> writes:

> This is not a question about preventing accidental multiple evaluation
> in macros, but rather about forcing multiple evaluation in functions.
>
> Let's say I want to create a list of 5 random numbers like this:
>
> (make-list 5 :initial-element (random 1.0))
>
> This gives me a list of 5 identical numbers, because (random 1.0) is
> only evaluated once before being passed to make-list. Is there away
> around this?

(loop repeat 5 collect (random 1.0))
--> (0.5119852 0.662104 0.40742368 0.6803096 0.6618643) ; for example

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

This universe shipped by weight, not volume.  Some expansion may have
occurred during shipment.
From: Stephen Compall
Subject: Re: Multiple evaluation
Date: 
Message-ID: <m2prp1h280.fsf@member.fsf.org>
Ari Krupnik <···@lib.aero> writes:
> (make-list 5 :initial-element (random 1.0))
>
> This gives me a list of 5 identical numbers, because (random 1.0) is
> only evaluated once before being passed to make-list. Is there away
> around this?

Interestingly, there is a form that will do what you want that is very
lexically similar:

(list . #.(make-list 5 :initial-element '(random 1.0)))

-- 
a Mr. Fleming wishes to study bugs in smelly cheese; a Polish woman
wishes to sift through tons of Central African ore to find minute
quantities of a substance she says will glow in the dark; a Mr. Kepler
wants to hear the songs the planets sing.
	--Carl Sagan, "The Demon-Haunted World"
From: Ari Krupnik
Subject: Re: Multiple evaluation
Date: 
Message-ID: <86r69hnqvb.fsf@deb.lib.aero>
Stephen Compall <···@member.fsf.org> writes:

> Ari Krupnik <···@lib.aero> writes:
>> (make-list 5 :initial-element (random 1.0))
>>
>> This gives me a list of 5 identical numbers, because (random 1.0) is
>> only evaluated once before being passed to make-list. Is there away
>> around this?
>
> Interestingly, there is a form that will do what you want that is very
> lexically similar:
>
> (list . #.(make-list 5 :initial-element '(random 1.0)))

Whoa! I don't even know how to read this. I gather #. is a reader
macro that means evaluate at read time. I don't understand what the
dot before it means. Does the result of the #. become the CDR of
arguments to LIST? I'm confused.

Ari.

-- 
Elections only count as free and trials as fair if you can lose money
betting on the outcome.
From: Pascal J. Bourguignon
Subject: Re: Multiple evaluation
Date: 
Message-ID: <87ej5h89h7.fsf@hubble.informatimago.com>
Ari Krupnik <···@lib.aero> writes:

> Stephen Compall <···@member.fsf.org> writes:
>
>> Ari Krupnik <···@lib.aero> writes:
>>> (make-list 5 :initial-element (random 1.0))
>>>
>>> This gives me a list of 5 identical numbers, because (random 1.0) is
>>> only evaluated once before being passed to make-list. Is there away
>>> around this?
>>
>> Interestingly, there is a form that will do what you want that is very
>> lexically similar:
>>
>> (list . #.(make-list 5 :initial-element '(random 1.0)))
>
> Whoa! I don't even know how to read this. I gather #. is a reader
> macro that means evaluate at read time. I don't understand what the
> dot before it means. Does the result of the #. become the CDR of
> arguments to LIST? I'm confused.

Ok. So you guessed it was some read time expression.  To see what it
gives, of course you will have to read it:

(read-from-string "(list . #.(make-list 5 :initial-element '(random 1.0)))")
--> (LIST (RANDOM 1.0) (RANDOM 1.0) (RANDOM 1.0) (RANDOM 1.0) (RANDOM 1.0)) ;
    55


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

ADVISORY: There is an extremely small but nonzero chance that,
through a process known as "tunneling," this product may
spontaneously disappear from its present location and reappear at
any random place in the universe, including your neighbor's
domicile. The manufacturer will not be responsible for any damages
or inconveniences that may result.
From: Ari Krupnik
Subject: Re: Multiple evaluation
Date: 
Message-ID: <86vdypn6br.fsf@deb.lib.aero>
···@informatimago.com (Pascal J. Bourguignon) writes:

>>> (list . #.(make-list 5 :initial-element '(random 1.0)))
>>
>> Whoa! I don't even know how to read this. I gather #. is a reader
>> macro that means evaluate at read time. I don't understand what the
>> dot before it means. Does the result of the #. become the CDR of
>> arguments to LIST? I'm confused.
>
> Ok. So you guessed it was some read time expression.  To see what it
> gives, of course you will have to read it:
>
> (read-from-string "(list . #.(make-list 5 :initial-element '(random 1.0)))")
> --> (LIST (RANDOM 1.0) (RANDOM 1.0) (RANDOM 1.0) (RANDOM 1.0) (RANDOM 1.0)) ;
>     55

I've never done read-time manipulation, and it took me some time to
figure out where read-time evaluation stopped and run-time began. I
guess this is equivalent to the following:

#.(cons 'list (make-list 5 :initial-element '(random 1.0)))

This raised an almost unrelated question for me. Dotted-list notation
is sort-of infix. Is that the only infix notation in CL (outside of
LOOP)?

Ari.


-- 
Elections only count as free and trials as fair if you can lose money
betting on the outcome.
From: Kent M Pitman
Subject: Re: Multiple evaluation
Date: 
Message-ID: <uk5f57gnv.fsf@nhplace.com>
Ari Krupnik <···@lib.aero> writes:

> ... Dotted-list notation is sort-of infix. Is that the only infix
> notation in CL (outside of LOOP)?

It's not infix, it just looks that way.  If it were infix, it would act
on its own, independent of the parens, as in 

 foo . bar

The dot is just an inert marker that is detected as the left paren collects
its contained forms moving rightward.
From: Dimiter "malkia" Stanev
Subject: Re: Multiple evaluation
Date: 
Message-ID: <6f6lmsFa2aj6U1@mid.individual.net>
Stephen Compall wrote:
> Ari Krupnik <···@lib.aero> writes:
>> (make-list 5 :initial-element (random 1.0))
>>
>> This gives me a list of 5 identical numbers, because (random 1.0) is
>> only evaluated once before being passed to make-list. Is there away
>> around this?
> 
> Interestingly, there is a form that will do what you want that is very
> lexically similar:
> 
> (list . #.(make-list 5 :initial-element '(random 1.0)))
> 

Tricky! I love it :)

So it works by generating code ((random 1.0) (random 1.0) ...) which is 
executed read-time, and then put back into the list!

I wish C++ had that!
From: Rainer Joswig
Subject: Re: Multiple evaluation
Date: 
Message-ID: <joswig-013B0C.23495428072008@news-europe.giganews.com>
In article <··············@mid.individual.net>,
 "Dimiter \"malkia\" Stanev" <······@gmail.com> wrote:

> Stephen Compall wrote:
> > Ari Krupnik <···@lib.aero> writes:
> >> (make-list 5 :initial-element (random 1.0))
> >>
> >> This gives me a list of 5 identical numbers, because (random 1.0) is
> >> only evaluated once before being passed to make-list. Is there away
> >> around this?
> > 
> > Interestingly, there is a form that will do what you want that is very
> > lexically similar:
> > 
> > (list . #.(make-list 5 :initial-element '(random 1.0)))
> > 
> 
> Tricky! I love it :)
> 
> So it works by generating code ((random 1.0) (random 1.0) ...) which is 
> executed read-time, and then put back into the list!
> 
> I wish C++ had that!

Check out what the reader does:

CL-USER 1 > (read-from-string "(list . #.(make-list 5 :initial-element '(random 1.0)))")

(LIST (RANDOM 1.0) (RANDOM 1.0) (RANDOM 1.0) (RANDOM 1.0) (RANDOM 1.0))

-- 
http://lispm.dyndns.org/
From: Sacha
Subject: Re: Multiple evaluation
Date: 
Message-ID: <gIrik.17529$wd5.3816@newsfe17.ams2>
Ari Krupnik wrote:
> This is not a question about preventing accidental multiple evaluation
> in macros, but rather about forcing multiple evaluation in functions.
> 
> Let's say I want to create a list of 5 random numbers like this:
> 
> (make-list 5 :initial-element (random 1.0))
> 
> This gives me a list of 5 identical numbers, because (random 1.0) is
> only evaluated once before being passed to make-list. Is there away
> around this?
> 
> 
> Ari.
> 


(make-list 5 :initial-element-fn (lambda ()(random 1.0)))

Sacha
From: Thomas A. Russ
Subject: Re: Multiple evaluation
Date: 
Message-ID: <ymizlo5qycy.fsf@blackcat.isi.edu>
Sacha <····@address.spam> writes:
> Ari Krupnik wrote:
> > Let's say I want to create a list of 5 random numbers like this:
> > (make-list 5 :initial-element (random 1.0))
> > This gives me a list of 5 identical numbers, because (random 1.0) is
> > only evaluated once before being passed to make-list. Is there away
> > around this?
> 
> 
> (make-list 5 :initial-element-fn (lambda ()(random 1.0)))

Unfortunately, there isn't any such keyword element in the Common Lisp
standard.  :INITIAL-ELEMENT is all you've got.

I think the best choice is:

  (loop repeat 5 collect (random 1.0))

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Sacha
Subject: Re: Multiple evaluation
Date: 
Message-ID: <4zvik.11694$Eo3.4646@newsfe14.ams2>
Thomas A. Russ wrote:
> Sacha <····@address.spam> writes:
>> Ari Krupnik wrote:
>>> Let's say I want to create a list of 5 random numbers like this:
>>> (make-list 5 :initial-element (random 1.0))
>>> This gives me a list of 5 identical numbers, because (random 1.0) is
>>> only evaluated once before being passed to make-list. Is there away
>>> around this?
>>
>> (make-list 5 :initial-element-fn (lambda ()(random 1.0)))
> 
> Unfortunately, there isn't any such keyword element in the Common Lisp
> standard.  :INITIAL-ELEMENT is all you've got.
> 
> I think the best choice is:
> 
>   (loop repeat 5 collect (random 1.0))
> 

Ahyes i wasn't aware of the make-list function ... I thought to OP was 
asking for a way of delaying evaluation. My mistake !


Sacha