I've taken a few months holiday from lisp and am finding a few
fundamental holes in my knowledge. For example, I want a function
that'll take a list and destructively add an element to a list, but I
can't get it.
A simplified example of what I'm trying:
(setq x (list 2 3))
(defun cons-1-to-list (list)
(push 1 list))
(cons-1-to-list x)
I'd like x to be (1 2 3) but I know that this doesn't work since the
list I'm pushing onto is just a copy of the list that I want to cons
onto. Do I need macros for this?
Lowell
Lowell Kirsh <······@cs.ubc.ca> wrote:
> (setq x (list 2 3))
> (defun cons-1-to-list (list)
> (push 1 list))
> (cons-1-to-list x)
> I'd like x to be (1 2 3) but I know that this doesn't work since the
> list I'm pushing onto is just a copy of the list that I want to cons
> onto. Do I need macros for this?
Nope. You need to understand how cons-cells/linked lists work. The
short answer is that you can't _destructively_ add elements to the
front of a shared linked list without using a containing structure
or a header cell. The key word here is shared: X points to the
first of cons of the list, in your function you do nothing that
changes that.
Consider:
(push foo bar)
means
(setq bar (cons foo bar)).
With boxes and pointers:
x = |1|->|2|->|3|->nil
After push:
x = |1|->|2|->|3|->nil
^
|
list = |1|
Do you see it?
Contrast and compare
(defvar x (list :header 1 2 3))
(defun cons-after-header (thing list)
(setf (cdr list) (cons thing (cdr list))))
(cons-after-header 0 x) ; => (0 1 2 3)
x ; => (:HEADER 0 1 2 3)
If confusion still reigns try SICP.
Cheers,
-- Nikodemus
ok, I guess i'll use macros. thanks.
·········@random-state.net wrote:
> Lowell Kirsh <······@cs.ubc.ca> wrote:
>
>
>>(setq x (list 2 3))
>>(defun cons-1-to-list (list)
>> (push 1 list))
>>(cons-1-to-list x)
>
>
>>I'd like x to be (1 2 3) but I know that this doesn't work since the
>>list I'm pushing onto is just a copy of the list that I want to cons
>>onto. Do I need macros for this?
>
>
> Nope. You need to understand how cons-cells/linked lists work. The
> short answer is that you can't _destructively_ add elements to the
> front of a shared linked list without using a containing structure
> or a header cell. The key word here is shared: X points to the
> first of cons of the list, in your function you do nothing that
> changes that.
>
> Consider:
>
> (push foo bar)
>
> means
>
> (setq bar (cons foo bar)).
>
> With boxes and pointers:
>
> x = |1|->|2|->|3|->nil
>
> After push:
>
> x = |1|->|2|->|3|->nil
> ^
> |
> list = |1|
>
> Do you see it?
>
> Contrast and compare
>
> (defvar x (list :header 1 2 3))
>
> (defun cons-after-header (thing list)
> (setf (cdr list) (cons thing (cdr list))))
>
> (cons-after-header 0 x) ; => (0 1 2 3)
>
> x ; => (:HEADER 0 1 2 3)
>
> If confusion still reigns try SICP.
>
> Cheers,
>
> -- Nikodemus
On Tue, 13 Apr 2004 00:48:28 -0700, Lowell Kirsh <······@cs.ubc.ca> wrote:
> I've taken a few months holiday from lisp and am finding a few
> fundamental holes in my knowledge. For example, I want a function
> that'll take a list and destructively add an element to a list, but
> I can't get it.
>
> A simplified example of what I'm trying:
>
> (setq x (list 2 3))
> (defun cons-1-to-list (list)
> (push 1 list))
> (cons-1-to-list x)
>
> I'd like x to be (1 2 3) but I know that this doesn't work since the
> list I'm pushing onto is just a copy of the list that I want to cons
> onto.
Not at all. The list you're pushing onto is the original list:
* (defparameter *x* (list 2 3))
*X*
* (defun cons-1-to-list (list)
(push 1 list))
CONS-1-TO-LIST
* (defparameter *y* (cons-1-to-list *x*))
*Y*
* *y*
(1 2 3)
* (setf (second *x*) 42)
42
* *x*
(2 42)
* *y*
(1 2 42)
See?
> Do I need macros for this?
Yes, because you obviously want to modify a 'place' (see 5.1 of the
ANSI standard). Try this one:
* (defmacro push-1 (place)
`(push 1 ,place))
PUSH-1
* (defparameter *x* (list 2 3))
*X*
* (push-1 *x*)
(1 2 3)
* *x*
(1 2 3)
Note that PUSH does all the work here. It would be tempting but subtly
false to write PUSH-1 like this:
(defmacro push-1 (place)
`(setf ,place (cons 1 ,place)))
This is not correct because the macro evaluates PLACE twice. To do
this correctly you need setf expanders which are also described in
5.1. Paul Graham's 'On Lisp'[1] explains how setf expanders are
used.
Edi.
[1] <http://www.paulgraham.com/onlisptext.html>
On Tue, 13 Apr 2004 00:48:28 -0700, Lowell Kirsh <······@cs.ubc.ca> wrote:
> I've taken a few months holiday from lisp and am finding a few
> fundamental holes in my knowledge. For example, I want a function
> that'll take a list and destructively add an element to a list, but I
> can't get it.
>
> A simplified example of what I'm trying:
>
> (setq x (list 2 3))
> (defun cons-1-to-list (list)
> (push 1 list))
> (cons-1-to-list x)
>
> I'd like x to be (1 2 3) but I know that this doesn't work since the
> list I'm pushing onto is just a copy of the list that I want to cons
> onto. Do I need macros for this?
>
> Lowell
I suggest's keeping track of the tail of the list and using rplacd.
(Got it from Norvig "Paradigms in AI")
--
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
John Thingstad wrote:
> On Tue, 13 Apr 2004 00:48:28 -0700, Lowell Kirsh <······@cs.ubc.ca> wrote:
>
>> I've taken a few months holiday from lisp and am finding a few
>> fundamental holes in my knowledge. For example, I want a function
>> that'll take a list and destructively add an element to a list, but I
>> can't get it.
>>
>> A simplified example of what I'm trying:
>>
>> (setq x (list 2 3))
>> (defun cons-1-to-list (list)
>> (push 1 list))
>> (cons-1-to-list x)
>>
>> I'd like x to be (1 2 3) but I know that this doesn't work since the
>> list I'm pushing onto is just a copy of the list that I want to cons
>> onto. Do I need macros for this?
>>
>> Lowell
>
>
> I suggest's keeping track of the tail of the list and using rplacd.
> (Got it from Norvig "Paradigms in AI")
>
You can also SETF the CAR and the CDR of the list, e.g.:
CL-USER> (setq $foo '(1 2 3))
(1 2 3)
CL-USER> (let ((old-car (car $foo))
(old-cdr (cdr $foo)))
(setf (car $foo) 0
(cdr $foo) (cons old-car old-cdr)))
(1 2 3)
CL-USER> $foo
(0 1 2 3)
Basically, you snag references to the old CAR and CDR, stuff a new value
into the CAR, and then CONS the old CAR onto the old CDR, and stuff the
result of that into the old CDR. The result is (sort of) like PUSH, but
mutates the original CONS cell so that it works in some cases where PUSH
doesn't (such as \where $foo is a parameter passed into a function and
you want the front of the list stored there to be altered after the
function returns).
In article <···················@newssvr25.news.prodigy.com>,
mikel <·····@evins.net> wrote:
> You can also SETF the CAR and the CDR of the list, e.g.:
Except, of course, when the original list is empty.
BTW, your example modified a quoted list -- that's a no-no.
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** Please don't copy me on replies. ***
Barry Margolin <······@alum.mit.edu> writes:
> In article <···················@newssvr25.news.prodigy.com>,
> mikel <·····@evins.net> wrote:
>
> > You can also SETF the CAR and the CDR of the list, e.g.:
>
> Except, of course, when the original list is empty.
>
> BTW, your example modified a quoted list -- that's a no-no.
This isn't the first time I've seen someone say that it is bad to
modify a quoted list (literal list, etc). I don't know how much this
is like modifying a string constant in C (that one normally expects
never to change). In any case, I don't get why it is bad. It seems
like a useful thing to be able to do.
I can just imagine the havoc you might be able to play with macros if
they are stored as Lisp lists. I guess you can't do the same to
compiled functions though as they have been turned into machine code.
Or are there operations you can do to that as well?
Maybe it would be bad style, but couldn't you do some interesting
things with quoted lists?
> *quoted-list-of-functions*
(a b c d)
>(mapcar #'funcall *quoted-list-of-functions*)
(w x y z)
>(destructively-randomize-list *quoted-list-of-functions*)
(c d a b)
>(mapcar #'funcall *quoted-list-of-functions*)
(y z w x)
Admittedly this is a silly example. Also the same effect could have
been acheived if *quoted-list-of-functions* was created this way:
>(defvar *quoted-list-of-functions* (list 'a 'b 'c 'd))
(a b c d)
Also something like this might only be useful with a healthy dose of
side effects.
--
I wouldn't mind the rat race so much if it wasn't for all the damn cats.
In article <··············@david-steuber.com>,
David Steuber <·····@david-steuber.com> wrote:
> This isn't the first time I've seen someone say that it is bad to
> modify a quoted list (literal list, etc). I don't know how much this
> is like modifying a string constant in C (that one normally expects
> never to change). In any case, I don't get why it is bad. It seems
> like a useful thing to be able to do.
Try this:
(defun test-func ()
(let ((temp-list '(1 2 3)))
(print temp-list)
(incf (car temp-list))
(values)))
Now run (test-func) a few times.
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** Please don't copy me on replies. ***
Barry Margolin <······@alum.mit.edu> writes:
> In article <··············@david-steuber.com>,
> David Steuber <·····@david-steuber.com> wrote:
>
> > This isn't the first time I've seen someone say that it is bad to
> > modify a quoted list (literal list, etc). I don't know how much this
> > is like modifying a string constant in C (that one normally expects
> > never to change). In any case, I don't get why it is bad. It seems
> > like a useful thing to be able to do.
>
> Try this:
>
> (defun test-func ()
> (let ((temp-list '(1 2 3)))
> (print temp-list)
> (incf (car temp-list))
> (values)))
>
> Now run (test-func) a few times.
$ sbcl
This is SBCL 0.8.9.35, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
* (defun test-func ()
(let ((temp-list '(1 2 3)))
(print temp-list)
(incf (car temp-list))
(values)))
TEST-FUNC
* (test-func)
(1 2 3)
* (test-func)
(2 2 3)
* (test-func)
(2 2 3)
* (test-func)
(2 2 3)
* (test-func)
(2 2 3)
*
Interesting. Incf only worked once. I would not have predicted
that. What's going on here?
--
I wouldn't mind the rat race so much if it wasn't for all the damn cats.
Under Corman i get the following:
> (defun test-func ()
(let ((temp-list '(1 2 3)))
(print temp-list)
(incf (car temp-list))
(values)))
TEST-FUNC
> (test-func)
(1 2 3) > (test-func)
(2 2 3) > (test-func)
(3 2 3) > (test-func)
(4 2 3) > (test-func)
(5 2 3) > (defconstant list '(1 2 3))
LIST
> (defun test-func ()
(princ list)
(incf (car list))
(values))
TEST-FUNC
> (test-func)
(1 2 3)> (test-func)
(2 2 3)> (test-func)
(2 2 3)> (test-func)
(2 2 3)> (test-func)
(2 2 3)> (fmakunbound 'test-func)
On 14 Apr 2004 17:26:59 -0400, David Steuber <·····@david-steuber.com>
wrote:
> Barry Margolin <······@alum.mit.edu> writes:
>
>> In article <··············@david-steuber.com>,
>> David Steuber <·····@david-steuber.com> wrote:
>>
>> > This isn't the first time I've seen someone say that it is bad to
>> > modify a quoted list (literal list, etc). I don't know how much this
>> > is like modifying a string constant in C (that one normally expects
>> > never to change). In any case, I don't get why it is bad. It seems
>> > like a useful thing to be able to do.
>>
>> Try this:
>>
>> (defun test-func ()
>> (let ((temp-list '(1 2 3)))
>> (print temp-list)
>> (incf (car temp-list))
>> (values)))
>>
>> Now run (test-func) a few times.
>
> $ sbcl
> This is SBCL 0.8.9.35, an implementation of ANSI Common Lisp.
> More information about SBCL is available at <http://www.sbcl.org/>.
>
> SBCL is free software, provided as is, with absolutely no warranty.
> It is mostly in the public domain; some portions are provided under
> BSD-style licenses. See the CREDITS and COPYING files in the
> distribution for more information.
> * (defun test-func ()
> (let ((temp-list '(1 2 3)))
> (print temp-list)
> (incf (car temp-list))
> (values)))
>
> TEST-FUNC
> * (test-func)
>
> (1 2 3)
> * (test-func)
>
> (2 2 3)
> * (test-func)
>
> (2 2 3)
> * (test-func)
>
> (2 2 3)
> * (test-func)
>
> (2 2 3)
> *
>
> Interesting. Incf only worked once. I would not have predicted
> that. What's going on here?
>
--
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Barry Margolin wrote:
> In article <··············@david-steuber.com>,
> David Steuber <·····@david-steuber.com> wrote:
>
>
>>This isn't the first time I've seen someone say that it is bad to
>>modify a quoted list (literal list, etc). I don't know how much this
>>is like modifying a string constant in C (that one normally expects
>>never to change). In any case, I don't get why it is bad. It seems
>>like a useful thing to be able to do.
>
>
> Try this:
>
> (defun test-func ()
> (let ((temp-list '(1 2 3)))
> (print temp-list)
> (incf (car temp-list))
> (values)))
>
> Now run (test-func) a few times.
>
Hmm hmm hmm...
when changing the '(1 2 3) to (list 1 2 3) the behaviour of the program
is as expected. When using the quoted list it does not act as I first
thought (now that I know it I (of course) expect this behaviour as normal).
This remembers me a bit of "unsigned" data types in C. One should avoid
them whenever possible, because it can also lead to errors, like:
unsigned int i=100;
for(; i>=0; i--) foo();
Andr�
--
In article <············@ulric.tng.de>,
Andr� Thieme <······································@justmail.de>
wrote:
> Hmm hmm hmm...
> when changing the '(1 2 3) to (list 1 2 3) the behaviour of the program
> is as expected. When using the quoted list it does not act as I first
> thought (now that I know it I (of course) expect this behaviour as normal).
Just read '(your list here) as a constant and you'll
never be tempted to destructively modify it. It's
not a gotcha, although as a feature, it is admittedly
latent.
Andr� Thieme <······································@justmail.de> writes:
> This remembers me a bit of "unsigned" data types in C. One should avoid
> them whenever possible, because it can also lead to errors, like:
>
> unsigned int i=100;
> for(; i>=0; i--) foo();
That's the most idiotic advice I've seen in a few days.
--
Raymond Wiker Mail: ·············@fast.no
Senior Software Engineer Web: http://www.fast.no/
Fast Search & Transfer ASA Phone: +47 23 01 11 60
P.O. Box 1677 Vika Fax: +47 35 54 87 99
NO-0120 Oslo, NORWAY Mob: +47 48 01 11 60
Try FAST Search: http://alltheweb.com/
Raymond Wiker wrote:
> Andr� Thieme <······································@justmail.de> writes:
>
>
>>This remembers me a bit of "unsigned" data types in C. One should avoid
>>them whenever possible, because it can also lead to errors, like:
>>
>>unsigned int i=100;
>>for(; i>=0; i--) foo();
>
>
> That's the most idiotic advice I've seen in a few days.
>
Why do you think did the Lispers who developed Java did not implement
an unsigned? Exactly for that reason... source of errors.
Too bad that expert Ray was not there ;-)
Andr�
--
Andr� Thieme <······································@justmail.de> writes:
> Raymond Wiker wrote:
>
>> Andr� Thieme <······································@justmail.de> writes:
>>
>>>This remembers me a bit of "unsigned" data types in C. One should avoid
>>>them whenever possible, because it can also lead to errors, like:
>>>
>>>unsigned int i=100;
>>>for(; i>=0; i--) foo();
>> That's the most idiotic advice I've seen in a few days.
>>
>
> Why do you think did the Lispers who developed Java did not implement
> an unsigned? Exactly for that reason... source of errors.
> Too bad that expert Ray was not there ;-)
How many times will foo() be called in the example above, if
you make i a signed int?
With that in mind, is your problem with unsigned data types,
or with the for loop?
--
Raymond Wiker Mail: ·············@fast.no
Senior Software Engineer Web: http://www.fast.no/
Fast Search & Transfer ASA Phone: +47 23 01 11 60
P.O. Box 1677 Vika Fax: +47 35 54 87 99
NO-0120 Oslo, NORWAY Mob: +47 48 01 11 60
Try FAST Search: http://alltheweb.com/
Raymond Wiker wrote:
> Andr� Thieme <······································@justmail.de> writes:
>
>
>>Raymond Wiker wrote:
>>
>>
>>>Andr� Thieme <······································@justmail.de> writes:
>>>
>>>
>>>>This remembers me a bit of "unsigned" data types in C. One should avoid
>>>>them whenever possible, because it can also lead to errors, like:
>>>>
>>>>unsigned int i=100;
>>>>for(; i>=0; i--) foo();
>>>
>>> That's the most idiotic advice I've seen in a few days.
>>>
>>
>>Why do you think did the Lispers who developed Java did not implement
>>an unsigned? Exactly for that reason... source of errors.
>>Too bad that expert Ray was not there ;-)
>
>
> How many times will foo() be called in the example above, if
> you make i a signed int?
The code i posted runs into an endless loop. Cause i is always 0 or
bigger. When it is 0 and i-- gets executed then i becomes (2^32)-1
(or whatever the word length of the specific machine might be).
If i would be signed it would stop after 101 iterations of foo().
Plus, code for unsigned types often is a bit less efficient.
> With that in mind, is your problem with unsigned data types,
> or with the for loop?
The unsigned data types.
Of course (!) they also have their use. I just wanted to point out that
they can (and in bigger programs are) a source of errors which are not
easy to find.
In Lisp this also can happen with the code posted earlier in this thread.
Andr�
--
Andr� Thieme <······································@justmail.de> writes:
>> With that in mind, is your problem with unsigned data types,
>> or with the for loop?
>
> The unsigned data types.
Personally, I have a problem with arrays because someone can loop
through the elements and forget to increment the index variable.
--
Rahul Jain
·····@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
"Andr� Thieme" <······································@justmail.de> wrote in
message ·················@ulric.tng.de...
> Raymond Wiker wrote:
>
> > Andr� Thieme <······································@justmail.de>
writes:
> >
> >
> >>This remembers me a bit of "unsigned" data types in C. One should avoid
> >>them whenever possible, because it can also lead to errors, like:
> >>
> >>unsigned int i=100;
> >>for(; i>=0; i--) foo();
> >
> >
> > That's the most idiotic advice I've seen in a few days.
> >
>
> Why do you think did the Lispers who developed Java did not implement
> an unsigned?
Simply because Java was designed for the "average programmer", so many
choices were made to remove features that could make newbies feel lost.
> Exactly for that reason... source of errors.
The source of errors is generally the programmer, not the language.
Would you reject CL macros altogether just because beginners usually
make lots of mistakes writing them?
--
Matthieu Villeneuve
Matthieu Villeneuve wrote:
> "Andr� Thieme" <······································@justmail.de> wrote in
> message ·················@ulric.tng.de...
>
>>Raymond Wiker wrote:
>>
>>
>>>Andr� Thieme <······································@justmail.de>
>
> writes:
>
>>>
>>>>This remembers me a bit of "unsigned" data types in C. One should avoid
>>>>them whenever possible, because it can also lead to errors, like:
>>>>
>>>>unsigned int i=100;
>>>>for(; i>=0; i--) foo();
>>>
>>>
>>> That's the most idiotic advice I've seen in a few days.
>>>
>>
>>Why do you think did the Lispers who developed Java did not implement
>>an unsigned?
>
>
> Simply because Java was designed for the "average programmer", so many
> choices were made to remove features that could make newbies feel lost.
For this reason CL and Java implemented the GC.
CL also has some restrictions like Java, for example you cannot redefine
standard functions (like LENGTH).
This is protecting the newbi and supporting the expert.
>>Exactly for that reason... source of errors.
>
> The source of errors is generally the programmer, not the language.
> Would you reject CL macros altogether just because beginners usually
> make lots of mistakes writing them?
Of course all errors are from humans.. a language itself can't be
"evil", so I agree.
And no, please don't skip the macros. However, a good Lisper will not
try to use a macro whenever he sees it would be /possible/ in a
situation. And a good C hacker will avoid unsigned's when possible.
Andr�
--
Andr� Thieme wrote:
> Matthieu Villeneuve wrote:
>
>> "Andr� Thieme" <······································@justmail.de>
>> wrote in
>> message ·················@ulric.tng.de...
>>
>>> Raymond Wiker wrote:
>>>
>>>
>>>> Andr� Thieme <······································@justmail.de>
>>
>>
>> writes:
>>
>>>>
>>>>> This remembers me a bit of "unsigned" data types in C. One should
>>>>> avoid
>>>>> them whenever possible, because it can also lead to errors, like:
>>>>>
>>>>> unsigned int i=100;
>>>>> for(; i>=0; i--) foo();
>>>>
>>>>
>>>>
>>>> That's the most idiotic advice I've seen in a few days.
>>>>
>>>
>>> Why do you think did the Lispers who developed Java did not implement
>>> an unsigned?
>>
>>
>>
>> Simply because Java was designed for the "average programmer", so many
>> choices were made to remove features that could make newbies feel lost.
>
>
> For this reason CL and Java implemented the GC.
> CL also has some restrictions like Java, for example you cannot redefine
> standard functions (like LENGTH).
> This is protecting the newbi and supporting the expert.
>
>
>>> Exactly for that reason... source of errors.
>>
>>
>> The source of errors is generally the programmer, not the language.
>> Would you reject CL macros altogether just because beginners usually
>> make lots of mistakes writing them?
>
>
> Of course all errors are from humans.. a language itself can't be
> "evil", so I agree.
> And no, please don't skip the macros. However, a good Lisper will not
> try to use a macro whenever he sees it would be /possible/ in a
> situation. And a good C hacker will avoid unsigned's when possible.
On the other hand, using unsigned consistently can improve
self-documentation of your interfaces (especially when warnings about
implicit conversions between signed and unsigned numbers are turned on).
Cheers,
Michael
Andr� Thieme <······································@justmail.de> writes:
> CL also has some restrictions like Java, for example you cannot redefine
> standard functions (like LENGTH).
Not at all. What happens when you _attempt_ to redefine LENGTH is
_un_defined.
> And no, please don't skip the macros. However, a good Lisper will not
> try to use a macro whenever he sees it would be /possible/ in a
> situation. And a good C hacker will avoid unsigned's when possible.
Wrong. A good programmer will use an abstraction that lets him/her
express what he/she _means_, not how it might be implemented for certain
CPUs with certain performance characteristics. Of course, that tends to
forbid them from using C, which, I suppose, means that they avoid using
C's unsigned type when possible. So I take that back. You were right. A
good C hacker will use Lisp when possible. ;)
--
Rahul Jain
·····@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
Andr� Thieme wrote:
> Hmm hmm hmm...
> when changing the '(1 2 3) to (list 1 2 3) the behaviour of the program
> is as expected. When using the quoted list it does not act as I first
> thought (now that I know it I (of course) expect this behaviour as normal).
Quoted lists are literal data. They should be regarded like numbers or
strings. When you say
(let ((var '(1 2 3))
(incf (car var)))
...this is like saying the following in Java.
4711++;
or
"abcd" += "efgh";
You're actually trying to change the source code of your program!
It's easier to prevent these things in languages like Java, because in
such languages code is treated as something fundamentally different from
data. However, Common Lisp allows you to put any object in your source
code, not just strings.
Pascal
--
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/
David Steuber <·····@david-steuber.com> writes:
> This isn't the first time I've seen someone say that it is bad to
> modify a quoted list (literal list, etc). I don't know how much this
> is like modifying a string constant in C (that one normally expects
> never to change).
It is analagous.
> In any case, I don't get why it is bad.
It is explicitly disallowed by the standard.
The compiler may put the list in read-only storage.
> It seems like a useful thing to be able to do.
``It seemed like a good idea at the time...''
--
~jrm
Joe Marshall <·············@comcast.net> writes:
> David Steuber <·····@david-steuber.com> writes:
>
> > This isn't the first time I've seen someone say that it is bad to
> > modify a quoted list (literal list, etc). I don't know how much this
> > is like modifying a string constant in C (that one normally expects
> > never to change).
>
> It is analagous.
>
> > In any case, I don't get why it is bad.
>
> It is explicitly disallowed by the standard.
>
> The compiler may put the list in read-only storage.
>
> > It seems like a useful thing to be able to do.
>
> ``It seemed like a good idea at the time...''
I think I get it now. And my silly example can be achieved within the
rules.
--
I wouldn't mind the rat race so much if it wasn't for all the damn cats.
Hi David Steuber,
> This isn't the first time I've seen someone say that it is bad to
> modify a quoted list (literal list, etc). I don't know how much this
> is like modifying a string constant in C (that one normally expects
> never to change). In any case, I don't get why it is bad. It seems
> like a useful thing to be able to do.
You basically have three options:
(a) Don't create a literal list in the first place (use LIST, which
creates fresh conses).
(b) Perform a deep copy of the literal list before destructively modifying
the copy (see COPY-TREE. Beware of the shallow COPY-LIST).
(c) Functional programming. Build new lists for output from functions
instead of destructively modifying inputs.
Option (c) is the most common approach. Literal lists are safe with this
approach and the promise of literal lists provides significant performance
benefits.
I guarantee that the shock about the consequences of literal lists will
pass (this appears to be a rite of passage).
> I can just imagine the havoc you might be able to play with macros if
> they are stored as Lisp lists.
This is very perceptive. Don't destructively modify the input arguments to
a macro. Return new source code s-expressions.
Regards,
Adam
Barry Margolin wrote:
> In article <···················@newssvr25.news.prodigy.com>,
> mikel <·····@evins.net> wrote:
>
>
>>You can also SETF the CAR and the CDR of the list, e.g.:
>
>
> Except, of course, when the original list is empty.
>
> BTW, your example modified a quoted list -- that's a no-no.
Why is it a "no-no"?
And btw, what is the difference between modifying
'(1 2 3)
and
(list 1 2 3) ?
Andr�
--
On Wed, 14 Apr 2004 01:37:33 +0200, Andr� Thieme wrote:
> Barry Margolin wrote:
>> In article <···················@newssvr25.news.prodigy.com>,
>> mikel <·····@evins.net> wrote:
>>
>>
>>>You can also SETF the CAR and the CDR of the list, e.g.:
>>
>>
>> Except, of course, when the original list is empty.
>>
>> BTW, your example modified a quoted list -- that's a no-no.
>
> Why is it a "no-no"?
>
> And btw, what is the difference between modifying
> '(1 2 3)
> and
> (list 1 2 3) ?
>
>
> Andr�
It's a no-no because '(1 2 3) is data that the compiler could put
somewhere read-only (e.g. in a ROM). Quoted lists are not
guaranteed to be modifiable, whereas (list 1 2 3) is always
modifiable because #'list creates new cons cells in an area of
memory that must be writable.
Feel free to jump in if I got something wrong but I believe that's
basically correct.
Cheers,
Bill.
--
Dr. William Bland www.abstractnonsense.com
Computer Programmer awksedgrep (Yahoo IM)
Any sufficiently advanced Emacs user is indistinguishable from magic
Hi André Thieme,
>> BTW, your example modified a quoted list -- that's a no-no.
>
> Why is it a "no-no"?
Quoted lists are literal objects which may be treated as immutable by the
compiler. Difficult to track down bugs will likely arise if you break
this constant promise to the compiler.
You can safely replace a binding (pointer) to a literal object. You cannot
safely destructively modify the literal object itself.
> And btw, what is the difference between modifying '(1 2 3) and (list 1 2 3)?
Do not destructively modify the quoted (') list. You implicitly made a
promise to the compiler that it will not be destructively modified. Your
code will not be portable and even if it works interpreted it will likely
break in non-obvious ways after being compiled.
Regards,
Adam