Hi! I'm a Lisp newbie and would like to get the following right:
I'm accessing an element of a list via "nth", then I look whether or
not it satisfies some test, and if it does, I'd like to set it to some
new value.
How do I store a reference to the element, so that "nth" is computed
only once?
So:
(setq P '(1 2 3 4 5 6))
(setq x (nth P 3))
(when (< x 5) (setf x "small")))
and I want to get
P
=> (1 2 3 "small" 5 6)
of course, this doesn't work...
In article <····························@posting.google.com>,
Martin <········@yahoo.de> wrote:
>Hi! I'm a Lisp newbie and would like to get the following right:
>
>I'm accessing an element of a list via "nth", then I look whether or
>not it satisfies some test, and if it does, I'd like to set it to some
>new value.
>How do I store a reference to the element, so that "nth" is computed
>only once?
>So:
>
>(setq P '(1 2 3 4 5 6))
>
>(setq x (nth P 3))
>
>(when (< x 5) (setf x "small")))
>
>and I want to get
>
>P
>=> (1 2 3 "small" 5 6)
>
>of course, this doesn't work...
(setq x (nthcdr 3 p))
(when (< (car x) 5) (setf (car x) "small"))
--
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
········@yahoo.de (Martin) writes:
> Hi! I'm a Lisp newbie and would like to get the following right:
>
> I'm accessing an element of a list via "nth", then I look whether or
> not it satisfies some test, and if it does, I'd like to set it to some
> new value.
> How do I store a reference to the element, so that "nth" is computed
> only once?
> So:
>
> (setq P '(1 2 3 4 5 6))
>
> (setq x (nth P 3))
>
> (when (< x 5) (setf x "small")))
>
> and I want to get
>
> P
> => (1 2 3 "small" 5 6)
>
> of course, this doesn't work...
I don't know whether the following is correct, but perhaps someone
who does will comment on it:
(let ((list (list 1 2 3 4 5 6)))
(dotimes (i (length list) list)
(symbol-macrolet ((x (nth i list)))
(when (< x 5) (setf x 'small)))))
==> (SMALL SMALL SMALL SMALL 5 6)
Andras
In article <···············@tarski.math.bme.hu>,
Simon Andr�s <······@math.bme.hu> wrote:
>I don't know whether the following is correct, but perhaps someone
>who does will comment on it:
>
>(let ((list (list 1 2 3 4 5 6)))
> (dotimes (i (length list) list)
> (symbol-macrolet ((x (nth i list)))
> (when (< x 5) (setf x 'small)))))
>
>==> (SMALL SMALL SMALL SMALL 5 6)
This doesn't require you to *write* NTH multiple times, but it will still
have to *compute* it in both places, since X will be macro-expanded into
(nth i list) in both places.
The OP is presumably trying to avoid having to scan down the list multiple
times, since that doubles the running time. See my response that uses
NTHCDR to find the cons.
--
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
* ········@yahoo.de (Martin)
| How do I store a reference to the element, so that "nth" is computed
| only once?
That is not how we do things in Common Lisp. In C-like languages, you
can compute a "reference" to the location of an object, i.e., some sort
of indirect object that does not refer to an object, but to another
pseudo-object that refers to this other object, and you can write into
pseud-objects from these indirect objects. Useful pseud-objects are
generally subobjects of various containers or aggregate object types,
such as array, structure, or class slots. Common Lisp does not offer you
any way to refer, directly or indirectly, to sub-objects, only to whole
objects. The cons cell that Barry Margolin suggested is basically the
smaalest container we have and nthcdr is the preferred way to access it.
Similarly simple accessors do not generally exist elsewhere.
However, this obsession with efficiency at this level is common to those
who have seen too much exposure to really bad languages, such as those in
the C family. There is nothing with the kind of pointers that C has, as
long as the programmer has no access to them. That is, if the compiler
can figure out that you will repeatedly refer to the same location, it
should be free to keep a pointer around rather than repeatedly re-compute
the same location, indeed, you should _expect_ this to be the case, but
there are limits to how far common subexpression elimination can get you,
so there is good reason to try to make the job easier for the compiler.
///
--
In a fight against something, the fight has value, victory has none.
In a fight for something, the fight is a loss, victory merely relief.
Erik Naggum <····@naggum.net> writes:
> there are limits to how far common subexpression elimination can get you,
> so there is good reason to try to make the job easier for the compiler.
Especially in the case of concurrency or preemptive multithreading.
Oh, and congrats on finally convincing me to change the quote in my
.sig ;)
--
-> -/ - Rahul Jain - \- <-
-> -\ http://linux.rice.edu/~rahul -=- ············@techie.com /- <-
-> -/ "Structure is nothing if it is all you got. Skeletons spook \- <-
-> -\ people if [they] try to walk around on their own. I really /- <-
-> -/ wonder why XML does not." -- Erik Naggum, comp.lang.lisp \- <-
|--|--------|--------------|----|-------------|------|---------|-----|-|
(c)1996-2002, All rights reserved. Disclaimer available upon request.