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)))
- Peder -
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
Regards,
Adam
This loops over the contents of the list, not over the
cons cells of the list. X takes on the values A, B, etc.
which are not cons cells.
To get the effect you want we can change one character:
(defun foo (lst)
(loop for x on lst do
(setf (car x) 'A)))
Here, X takes on the values (A B C D ...), (B C D ...), etc.
Btw, use of the name 'lst' marks you as a Schemer. :)
Paul
> 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.
-- Bruce
* 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.
> * 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.
Is that the sort of thing a "Schemer" would do?
-- Bruce
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'.
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.
> * 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.
-- Bruce
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.
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
> Barry Margolin <bar...@genuity.net> writes:
> > In article <y6cvg4q...@octagon.valis.nyu.edu>,
> > Marco Antoniotti <mar...@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.
* 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.
> * 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.
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.
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.
Yawn.
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).
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.
Regards,
Adam
[snip]
> 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.
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 ...)
--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
> 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:
(defmacro bind ((var val) &body forms)
`(let ((,var ,val)) ,@forms))
(bind (list 1)
list)
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:
(macrolet ((bind ((var val)) &body forms)
`(let ((,var ,val)) ,@forms))
(bind (list 1)
list))
It's quite hard to get this completely right.
--tim
>> (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.
>
> 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:
(funcall (read-from-string (coerce (list (code-char 76) (code-char 73)
(code-char 83) (code-char 84)) 'string)) 'list)
...(using ASCII/UTF-8 character codes) should be changed to:
(newlist 'list)
[To change all list function calls to newlist in the contrived example]
Naive approach methinks (or explicit version control).
Regards,
Adam
Thanks for how this would be approached Tim. Analysing Richard Waters'
macroexpand-all code would be a good start.
Given the example I just posted it would be impractical to get it
completely right.
Regards,
Adam
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.
,----
| USER> (defvar *walker-demo-form*
| (read-from-string
| "(let ((list (list 'list '(list 'list))))
| (write (list list))
| (write (funcall 'list list))
| (write '(list list)))"))
| *walker-demo-form*
| USER> (defun walker-demo (form)
| (flet ((walk-function (form context env)
| (declare (ignorable env))
| (cond ((not (eq context :eval)) form)
| ((not (listp form)) form)
| ((and (symbolp (first form))
| (fboundp (first form))
| (eq 'list (first form)))
| (cons 'newlist (rest form)))
| (t form))))
| (walker:walk-form form nil #'walk-function)))
| walker-demo
| USER> (walker-demo *walker-demo-form*)
| (let ((list (newlist 'list '(list 'list))))
| (write (newlist list))
| (write (funcall 'list list))
| (write '(list list)))
| USER> (defmacro bind ((var val) &body forms)
| `(let ((,var ,val)) ,@forms))
| bind
| USER> (walker-demo '(bind (list 1) list))
| (bind (list 1) list)
`----
--
Eric Marsden <URL:http://www.laas.fr/~emarsden/>
* (defvar x 137)
X
* x
137
* (let ((x 'dragon))
(list
x
(symbol-value 'x)))
(DRAGON DRAGON)
err, um, I expected (DRAGON 137)
* x
137
Well my old value of x is still there, so a symbol must have
multiple "symbol values", even when it is special. This
needs more investigation.
Alan Crowe, Edinburgh, Scotland
> 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.
--
Frode Vatvedt Fjeld
> * (defvar x 137)
> X
>
> * x
> 137
>
> * (let ((x 'dragon))
> (list
> x
> (symbol-value 'x)))
>
> (DRAGON DRAGON)
>
> err, um, I expected (DRAGON 137)
>
> * x
> 137
>
> Well my old value of x is still there, so a symbol must have
> multiple "symbol values", even when it is special. This
> needs more investigation.
X is globally special because you used DEFVAR. Therefore your LET
binds the dynamic variable X to a new value during the execution of
this form.
Consider this:
(defun foo1 ()
(declare (special x))
(let ((x 42))
(list x (symbol-value 'x))))
(defun foo2 ()
(let ((x 42))
(declare (special x))
(list x (symbol-value 'x))))
(defun bar (function)
(let ((x 'frob))
(declare (special x))
(funcall function)))
* (bar #'foo1)
(42 FROB)
* (bar #'foo2)
(42 42)
Due to your DEFVAR you implicitely used the FOO2 mechanism where I
think you expected FOO1 behaviour.
Look at the entry for LET in the CLHS where it says that "each binding
is lexical unless there is a special declaration to the contrary". So
Erik Naggum was of course right when he said that lexical bindings do
not affect the SYMBOL-VALUE. However, your example wasn't about
lexical bindings.
Edi.
:)w
[1] The online version is available here (and other places):
www.ida.liu.se/imported/cltl/clm/clm.html
;)w
* (defvar x 137)
> X
* x
> 137
* (let ((x 'dragon))
> (list
> x
> (symbol-value 'x)))
That's not a lexical binding, it's a special binding. Once you've
done a DEFVAR on something it's special for ever - you can never make
it lexical again.
--tim
I didn't understand your motivation for this example,
but converting the example itself seems a lost cause.
Your only way out is to follow the Paul Graham tack of
scrupulously abstaining from the ability to use the
same symbol as both operator name and non-operator
variable. Once you do that, of course, you aren't
really exploiting the vaunted freedom of a Lisp2
anymore. You are writing as a Lisp1er (eg, Schemer)
would, except that, unlike them, you are still saddled
with the funcall/#' machinery even though it
isn't buying you anything in an informational sense.
* Alan S. Crowe
| Well my old value of x is still there, so a symbol must have multiple
| "symbol values", even when it is special. This needs more investigation.
It is not a lexical binding when it is special. /THINK/!
> 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>.
And which is also (one of the reasons) why it is (usually) a good idea
to have asterisks around the names of special variables. (Whether
global or not.)
---Vassil.
> I didn't understand your motivation for this example,
> but converting the example itself seems a lost cause.
This is obviously false. Anything which understands the code - such
as a correct code walker - can do this kind of replacement. One
canonical example of such a program is an interpreter or compiler, and
several Lisp environments have compilers which maintain databases of
where functions (and less commonly, but obviously possibly) variables
are used and provided user access to them. I think at least one
InterLisp system, for instance, allowed you to specify replacements on
programs, relying on this kind of information (and possibly also
allowing pattern-based substitutions too).
In general, I can't see the reason for changing lexically bound
variable names, since (in a Lisp2) they never really matter - the
exceptions being when you want to unify or split two variables. Those
exceptions can't really be done mechanically since they obviously
change the program semantics. Dynamic variables are clearly more
interesting to track (and not surprisingly the various
compiler/database systems do tend to track bindings of & references
too specials).
--tim
> In general, I can't see the reason for changing lexically bound
> variable names...
Avoiding name collisions when inlining.
> Avoiding name collisions when inlining.
Oh, yes that's a very good reason. What I meant was as an editorial
change to source code, not as something done during
compilation/evaluation - sorry not to be clearer...
--tim
If so, it would also be impossible to execute. Is it?
| Your only way out is to follow the Paul Graham tack of scrupulously
| abstaining from the ability to use the same symbol as both operator name
| and non-operator variable.
I think you should say "my only way out" when that is what you mean.
| You are writing as a Lisp1er (eg, Schemer) would, except that, unlike
| them, you are still saddled with the funcall/#' machinery even though it
| isn't buying you anything in an informational sense.
I think products and vendors should be judged by the intelligence of
their marketing. So Scheme must be the choice of the pretty dumb.