Say I have a function foo that is supposed to take a list as input (A B C D...). The function will then traverse the list looking for an element, and change that element. That's basically it.
For example, say, the function shall set all elements of lst to 'A: Why is this wrong?
(defun foo (lst) (loop for x in lst do (setf (car x) 'A)))
> Say I have a function foo that is supposed to take a list as input (A > B C D...). The function will then traverse the list looking for an > element, and change that element. That's basically it.
> For example, say, the function shall set all elements of lst to 'A: > Why is this wrong?
> (defun foo (lst) > (loop for x in lst do > (setf (car x) 'A)))
Unless you have a particular need to perform destructive modification of the input list Peder just create another list:
(defun foo (list) (loop for x in list collect 'A))
You tried to find the car of a symbol. As you loop through the list x contains elements of the list.
[1]> (setf list '(a b c d)) (A B C D) [2]> (listp list) T [3]> (listp (first list)) NIL
* Paul F. Dietz | Btw, use of the name 'lst' marks you as a Schemer. :)
* Bruce Hoult | Paul Graham uses "lst" throughout _On Lisp_, from the tutorial section to | the mini-CLOS implementation at the end.
I read this as affirming Paul's point. But why bother affirming it, so I think perhaps you meant to contradict it. Would you care to explain why you think «On Lisp» is not an effort to bring some of Scheme into Common Lisp? (Please note that he has said so himself.)
-- Erik Naggum, Oslo, Norway
Act from reason, and failure makes you rethink and study harder. Act from faith, and failure makes you blame someone and push harder.
In article <3242210758749...@naggum.no>, Erik Naggum <e...@naggum.no> wrote:
> * Paul F. Dietz > | Btw, use of the name 'lst' marks you as a Schemer. :)
> * Bruce Hoult > | Paul Graham uses "lst" throughout _On Lisp_, from the tutorial section to > | the mini-CLOS implementation at the end.
> I read this as affirming Paul's point. But why bother affirming it, so I > think perhaps you meant to contradict it. Would you care to explain why you > think «On Lisp» is not an effort to bring some of Scheme into Common Lisp? > (Please note that he has said so himself.)
He has? Where?
Certainly, the chapter on getting many of the effects of call/cc in CL (by defining macros such as =defun, =values, etc that manipulate explicitly-passed continuations) would qualify as an effort to bring *some* of Scheme into Common Lisp.
On the other hand, it's also an illustration that you don't necessarily need those features built in if you can implement them yourself using a sufficiently powerful macro system.
In fact that appears to be the point of the whole book. That CL's powerful macros are the prime thing that distinguishes it from lesser languages, such as Scheme.
pyda...@ec.auckland.ac.nz (Peder Y) writes: > Say I have a function foo that is supposed to take a list as input (A > B C D...). The function will then traverse the list looking for an > element, and change that element. That's basically it.
> For example, say, the function shall set all elements of lst to 'A: > Why is this wrong?
> (defun foo (lst) > (loop for x in lst do > (setf (car x) 'A)))
The above will not necessarily work because you are changing the list as you are traversing it. This is specifically mentioned in the language standard.
To do that kind of things you should look to the standard functions SUBSTITUTE and NSUBSTITUTE.
Cheers
-- Marco Antoniotti ======================================================== NYU Courant Bioinformatics Group tel. +1 - 212 - 998 3488 715 Broadway 10th Floor fax +1 - 212 - 995 4122 New York, NY 10003, USA http://bioinformatics.cat.nyu.edu "Hello New York! We'll do what we can!" Bill Murray in `Ghostbusters'.
* Bruce Hoult <br...@hoult.org> | Is that the sort of thing a "Schemer" would do?
It is the sort of thing that somebody who likes Scheme better than Common Lisp would do.
-- Erik Naggum, Oslo, Norway Today, the sum total of the money I would retain from the offers in the more than 7500 Nigerian 419 scam letters received in the past 33 months would have exceeded USD 100,000,000,000. You can stop sending me more offers, now.
In article <3242227234320...@naggum.no>, Erik Naggum <e...@naggum.no> wrote:
> * Bruce Hoult <br...@hoult.org> > | Is that the sort of thing a "Schemer" would do?
> It is the sort of thing that somebody who likes Scheme better than Common > Lisp would do.
Seems to me that person would actually write a book called _On Scheme_, which showed how to implement features they liked from Common Lisp and Prolog on top of Scheme.
>> Say I have a function foo that is supposed to take a list as input (A >> B C D...). The function will then traverse the list looking for an >> element, and change that element. That's basically it.
>> For example, say, the function shall set all elements of lst to 'A: >> Why is this wrong?
>> (defun foo (lst) >> (loop for x in lst do >> (setf (car x) 'A)))
>The above will not necessarily work because you are changing the list >as you are traversing it. This is specifically mentioned in the >language standard.
I haven't checked the reference, but I'm pretty sure this is a case that's specifically *allowed* by the standard. When traversing a list, it's OK to modify the CAR of the current element, but not the CDRs.
-- Barry Margolin, bar...@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.
Barry Margolin <bar...@genuity.net> writes: > In article <y6cvg4qt4za....@octagon.valis.nyu.edu>, > Marco Antoniotti <marc...@cs.nyu.edu> wrote: > >pyda...@ec.auckland.ac.nz (Peder Y) writes: > >> For example, say, the function shall set all elements of lst to 'A: > >> Why is this wrong?
> >> (defun foo (lst) > >> (loop for x in lst do > >> (setf (car x) 'A)))
> >The above will not necessarily work because you are changing the list > >as you are traversing it. This is specifically mentioned in the > >language standard.
> I haven't checked the reference, but I'm pretty sure this is a case that's > specifically *allowed* by the standard. When traversing a list, it's OK to > modify the CAR of the current element, but not the CDRs.
As posted, it's just bust. If it were (loop for x ON lst do ...), then I think it's OK by the standard. Section 3.6 ("Traversal Rules and Side Effects") says:
List traversal For list traversal operations, the cdr chain of the list is not allowed to be destructively modified.
Which suggests to me that mutating the CAR is OK.
Cheers, M.
-- The Programmer's Quick Guide To Python (Time Machine version): You try to shoot yourself in the foot, only to realize that there's no need, since Guido thoughtfully shot you in the foot years ago. -- Nick Mathewson, comp.lang.python
Michael Hudson <m...@python.net> writes: > Barry Margolin <bar...@genuity.net> writes: > > In article <y6cvg4qt4za....@octagon.valis.nyu.edu>, > > Marco Antoniotti <marc...@cs.nyu.edu> wrote: ...
> > I haven't checked the reference, but I'm pretty sure this is a case that's > > specifically *allowed* by the standard. When traversing a list, it's OK to > > modify the CAR of the current element, but not the CDRs.
> As posted, it's just bust. If it were (loop for x ON lst do ...), > then I think it's OK by the standard. Section 3.6 ("Traversal Rules > and Side Effects") says:
> List traversal > For list traversal operations, the cdr chain of the list is not > allowed to be destructively modified.
> Which suggests to me that mutating the CAR is OK.
Thanks to you and Barry. It does look like changing the CAR of a list while traversing is ok.
Cheers
-- Marco Antoniotti ======================================================== NYU Courant Bioinformatics Group tel. +1 - 212 - 998 3488 715 Broadway 10th Floor fax +1 - 212 - 995 4122 New York, NY 10003, USA http://bioinformatics.cat.nyu.edu "Hello New York! We'll do what we can!" Bill Murray in `Ghostbusters'.
* Peder Y | (defun foo (lst) | (loop for x in lst do | (setf (car x) 'A)))
* Marco Antoniotti | The above will not necessarily work because you are changing the list as you | are traversing it. This is specifically mentioned in the language standard.
Huh? The only way the above code would work is by changing the car of each cons cell that is the car of the cons cells that are traversed. This is not even close to the restriction of modifying the list structure itself, which also means the cdr. But even (cdr x) would be just fine, because it would only modify the conses that were the elements of the list.
In particular, after (foo bar), bar would have a contents like ((A ...) (A ...) (A ...) ...).
-- Erik Naggum, Oslo, Norway
Act from reason, and failure makes you rethink and study harder. Act from faith, and failure makes you blame someone and push harder.
Erik Naggum <e...@naggum.no> writes: > * Peder Y > | (defun foo (lst) > | (loop for x in lst do > | (setf (car x) 'A)))
> * Marco Antoniotti > | The above will not necessarily work because you are changing the list as you > | are traversing it. This is specifically mentioned in the language standard.
> Huh? The only way the above code would work is by changing the car of each > cons cell that is the car of the cons cells that are traversed. This is not > even close to the restriction of modifying the list structure itself, which > also means the cdr. But even (cdr x) would be just fine, because it would > only modify the conses that were the elements of the list.
> In particular, after (foo bar), bar would have a contents like > ((A ...) (A ...) (A ...) ...).
Yep. My mistake.
Cheers
-- Marco Antoniotti ======================================================== NYU Courant Bioinformatics Group tel. +1 - 212 - 998 3488 715 Broadway 10th Floor fax +1 - 212 - 995 4122 New York, NY 10003, USA http://bioinformatics.cat.nyu.edu "Hello New York! We'll do what we can!" Bill Murray in `Ghostbusters'.
In article <bruce-C9E44F.01552229092...@copper.ipg.tsnz.net>, Bruce Hoult <br...@hoult.org> wrote:
>In article <3D959BFC.D1305...@dls.net>, "Paul F. Dietz" <di...@dls.net> >wrote:
>> Btw, use of the name 'lst' marks you as a Schemer. :)
>Paul Graham uses "lst" throughout _On Lisp_, from the tutorial section >to the mini-CLOS implementation at the end.
Paul Graham's use of "lst" is probably because he wants to keep his code usable, with minimal or automatable translation, in Scheme also. Which would help those who are using his book privately to learn Lisp principles but trying out his examples in Scheme. I've seen this kind of honorable eclecticism in other books too, notably the Little Schemer, where footnotes quietly identify how to run the examples in Common Lisp.
Are there any CL tutorial books that actually advise using the same symbol for both its symbol-value and its symbol-function (holding different values)? I have seen at least one -- I think it was the Winston and Horn -- that counseled against this practice because it is "confusing"!!! Perhaps they have the same rationale as Graham, because in the streams (as in delayed lists, not ports) chapter, they explicitly mention, somewhat ruefully, that Scheme streams would have a cleaner syntax.
* Dorai Sitaram | Are there any CL tutorial books that actually advise using the same | symbol for both its symbol-value and its symbol-function (holding | different values)?
But that is not what anyone argues for. Lexical bindings do not affect the symbol-value of a the symbol used. Some precision here is good.
-- Erik Naggum, Oslo, Norway
Act from reason, and failure makes you rethink and study harder. Act from faith, and failure makes you blame someone and push harder.
> In article <bruce-C9E44F.01552229092...@copper.ipg.tsnz.net>, Bruce > Hoult <br...@hoult.org> wrote: >>In article <3D959BFC.D1305...@dls.net>, "Paul F. Dietz" <di...@dls.net> >>wrote:
>>> Btw, use of the name 'lst' marks you as a Schemer. :)
>>Paul Graham uses "lst" throughout _On Lisp_, from the tutorial section >>to the mini-CLOS implementation at the end.
> Paul Graham's use of "lst" is probably because he wants to keep his code > usable, with minimal or automatable translation, in Scheme also. Which > would help those who are using his book privately to learn Lisp > principles but trying out his examples in Scheme. I've seen this kind > of honorable eclecticism in other books too, notably the Little Schemer, > where footnotes quietly identify how to run the examples in Common Lisp.
> Are there any CL tutorial books that actually advise using the same > symbol for both its symbol-value and its symbol-function (holding > different values)? I have seen at least one -- I think it was the > Winston and Horn -- that counseled against this practice because it is > "confusing"!!! Perhaps they have the same rationale as Graham, because > in the streams (as in delayed lists, not ports) chapter, they explicitly > mention, somewhat ruefully, that Scheme streams would have a cleaner > syntax.
I love the freedom of separate namespaces. But perhaps I can receive some help on a related question.
I am updating syntax and function names on a regular basis in the document format I'm developing. So that legacy documents don't have to be manually updated I upgrade them automatically. I love the way I can read in lists of Lisp code as data and process them without operating on the code at the character level (and I set *print-case* to :downcase so the updated code doesn't start shouting).
But how should I proceed with automatically updating code when a variable/symbol name may be the same as a function name and I only want to update the function name (or vice versa)? Is there any built-in way to find out whether something is referring to a function/macro or do I have to parse the syntax manually (for example noting that a particular list is quoted and therefore the symbol at the start of a list doesn't refer to a function).
In Richard C. Waters Macroexpand-All: An Example of a Simple Lisp Code Walker http://www.merl.com/papers/TR93-17/ it states that there are 25 special forms and each has its own special semantics. It seems that if I want to be able to robustly update code that I have to understand many of these special forms so I do not accidentally modify a variable name instead of a non-function name with the same name, etc. (it's similar to the list/list issue).
What would be the robust way of processing this code so that only the function name list is changed to newlist? Some of the difficulty in parsing this code arises out of the separate namespaces.
> I am updating syntax and function names on a regular basis in the document > format I'm developing. So that legacy documents don't have to be manually > updated I upgrade them automatically. I love the way I can read in lists > of Lisp code as data and process them without operating on the code at the > character level (and I set *print-case* to :downcase so the updated code > doesn't start shouting).
> But how should I proceed with automatically updating code when a > variable/symbol name may be the same as a function name and I only want to > update the function name (or vice versa)? Is there any built-in way to
[snip]
> Maybe a simple example could focus the question:
> What would be the robust way of processing this code so that only the > function name list is changed to newlist? Some of the difficulty in > parsing this code arises out of the separate namespaces.
While I always hesitate to say anything is impossible, I don't see how this could be. Even the almighty human brain can not look at that and make the substitution without knowing what the semantics of your application are. How can I know that '(list list) or 'list is data, not code? Being quoted does not prove that, as you said code is data in lisp. What about (mapcar 'list ...)?
I think the best you could do would be a naive approach that assumed no code is being passed around as data and no functions are passed symbols instead of function objects (ie #'list), then you could globally replace all occurences of <(target > and <#'target > with many messy exceptions (like LET ...)
* Adam Warner wrote: > Maybe a simple example could focus the question: > (let ((list (list '(list 'list)))) > (write (list list)) > (write '(list list))) > What would be the robust way of processing this code so that only the > function name list is changed to newlist? Some of the difficulty in > parsing this code arises out of the separate namespaces.
You need a code walker. This has to understand all the special forms defined by the language, as well as being able to do full macroexpansion. For instance, it needs to know that if I've said:
That the occurrence of LIST isn't a function call. The way to know this is to do macroexpansion.
Note that the code walker needs to take note of macros you define as well as CLs. Partly this can be done by just assuming that you've already loaded your system, but even this is not quite enough:
>> What would be the robust way of processing this code so that only the >> function name list is changed to newlist? Some of the difficulty in >> parsing this code arises out of the separate namespaces.
> While I always hesitate to say anything is impossible, I don't see how > this could be. Even the almighty human brain can not look at that and > make the substitution without knowing what the semantics of your > application are. How can I know that '(list list) or 'list is data, not > code? Being quoted does not prove that, as you said code is data in > lisp. What about (mapcar 'list ...)?
> I think the best you could do would be a naive approach that assumed no > code is being passed around as data and no functions are passed symbols > instead of function objects (ie #'list), then you could globally replace > all occurences of <(target > and <#'target > with many messy exceptions > (like LET ...)
Thanks for the insights Coby. I would hesitate to say it is impossible because it must be possible to trace back from the function calls to what generated them. But I see now that it would require something many times more complicated and intelligent than the original interpreter/compiler. To give another example from your insights, what sort of AI would be able to deduce that this code:
>> What would be the robust way of processing this code so that only the >> function name list is changed to newlist? Some of the difficulty in >> parsing this code arises out of the separate namespaces.
> You need a code walker. This has to understand all the special forms > defined by the language, as well as being able to do full > macroexpansion. For instance, it needs to know that if I've said:
> That the occurrence of LIST isn't a function call. The way to know this > is to do macroexpansion.
> Note that the code walker needs to take note of macros you define as > well as CLs. Partly this can be done by just assuming that you've > already loaded your system, but even this is not quite enough:
>>>>> "aw" == Adam Warner <use...@consulting.net.nz> writes:
aw> Maybe a simple example could focus the question: aw> aw> (let ((list (list '(list 'list)))) aw> (write (list list)) aw> (write '(list list))) aw> aw> What would be the robust way of processing this code so that only the aw> function name list is changed to newlist? Some of the difficulty in aw> parsing this code arises out of the separate namespaces.
Here is how to do this using the PCL code walker (available with CMUCL). The walker allows you to distinguish between uses of the symbol list as a function and as data, including Tim's example of a macro that changes the symbol binding. However, it won't detect uses of the list function via FUNCALL; that requires whole program analysis in the general case.
a...@cawtech.freeserve.co.uk (Alan S. Crowe) writes:
> err, um, I expected (DRAGON 137)
What (defvar <x> ..) does, among other things, is to proclaim <x> to be a special variable. One consequence of this is that it will be _impossible_ to create a lexical binding for <x>. So when (let ((<x> ..)) is later evaluated or compiled, a dynamic binding is created.
> Well my old value of x is still there, so a symbol must have > multiple "symbol values", even when it is special.
Each symbol has as many symbol-values as it has bindings in a particular (dynamic) scope. But only the last/innermost binding's value is available to you.