Does my macro create C style pointers?
From: Alan Crowe (alan_at_cawtech.freeserve.co.uk)
Date: 09/21/04
- Next message: Pascal Bourguignon: "Re: Sharp-colon reader macro"
- Previous message: Christophe Rhodes: "Re: LispWorks' warnings output"
- Next in thread: Pascal Bourguignon: "Re: Does my macro create C style pointers?"
- Reply: Pascal Bourguignon: "Re: Does my macro create C style pointers?"
- Reply: Chris Capel: "Re: Does my macro create C style pointers?"
- Reply: Lars Brinkhoff: "Re: Does my macro create C style pointers?"
- Reply: Alan Crowe: "Re: Does my macro create C style pointers? (correction)"
- Reply: Rahul Jain: "Re: Does my macro create C style pointers?"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: 21 Sep 2004 21:54:40 +0100
In C you can pass the address of a variable to a function,
allowing the function to update the value of the variable.
CL's lexical variables don't permit this. If you are "old
school" then you make free use of dynamic scope and might
pass a symbol where C code would pass an address. For
example:
(defun inc-func(symbol)
(incf (symbol-value symbol))
lets you write
(let ((x 100))
(declare (special x))
(inc-func 'x)
x) => 101
However, the semantics are not quite the same. The variable
can be captured by a special binding of the same symbol
along the call path. I've created two intermediate
functions to illustrate the point
(defun intermediate1 (symbol)
(let ((x -1)) ;lexical
(inc-func symbol)
(format t "~&First intermediate x: ~A" x)))
(defun intermediate2 (symbol)
(let ((x -1))
(declare (special x))
(inc-func symbol)
(format t "~&Second intermediate x: ~A" x)))
(let ((x 100))
(declare (special x))
(intermediate1 (quote x))
(format t "~&First value of outer x: ~A" x)
(intermediate2 (quote x))
(format t "~&Second value of outer x: ~A" x))
=>
First intermediate x: -1
First value of outer x: 101
Second intermediate x: 0
Second value of outer x: 101
Whoops, the second intermediate function grabbed the symbol x, and
got its x incremented leaving the outer x unchanged. Sometimes that is
exactly what you want
(let ((*readtable* *readtable*))
(mess-with-readtable) ...
is a good way of making sure that the changes are undone at the end of
the let form. But what if you want
(pointer (x 100)
(intermediate1 &x)
(format t "~&First value of outer x: ~A" x)
(intermediate2 &x)
(format t "~&Second value of outer x: ~A" x))
=>
First intermediate x: -1
First value of outer x: 101
Second intermediate x: -1
Second value of outer x: 102
without any risk of variable capture
(defmacro pointer ((name initial-value) &body code)
(let ((hidden-symbol (gensym))
(addr-name (intern (format nil "&~A" name))))
`(let ((,addr-name (quote ,hidden-symbol)))
(symbol-macrolet ((,name ,hidden-symbol))
(let ((,hidden-symbol ,initial-value))
(declare (special ,hidden-symbol))
,@code)))))
seems to do the trick.
Have I created an exact equivalent to the C idiom of taking
the address of a variable? As far as I can see tonight, I
have suceeded all too well, even reproducing the dynamic
extent of such an address.
Baron Alan Frankenstein
Edinburgh Castle
Scotland
- Next message: Pascal Bourguignon: "Re: Sharp-colon reader macro"
- Previous message: Christophe Rhodes: "Re: LispWorks' warnings output"
- Next in thread: Pascal Bourguignon: "Re: Does my macro create C style pointers?"
- Reply: Pascal Bourguignon: "Re: Does my macro create C style pointers?"
- Reply: Chris Capel: "Re: Does my macro create C style pointers?"
- Reply: Lars Brinkhoff: "Re: Does my macro create C style pointers?"
- Reply: Alan Crowe: "Re: Does my macro create C style pointers? (correction)"
- Reply: Rahul Jain: "Re: Does my macro create C style pointers?"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|