[Openmcl-devel] Where is the source of LET* macro

Tim Bradshaw tfb at tfeb.org
Fri Apr 14 14:50:10 PDT 2023


The trouble is that, if declarations should apply to all bindings of a given name in a given form (which I believe they should, probably) then

(let* ((x ...) (x ...)) (declare (special x)) ...)

is *not* equivalent to

(let ((x ...)) (let ((x ...)) (declare (special x)) ...))

but to

(let ((x ...)) (declare (special x)) (let ((x ...)) (declare (special x)) ...))

My form was meant to tease these cases apart: I believe that CCL & LW exhibit correct behaviour here.  However my belief in that is only because (unless I have missed it in the standard) anything else requires quite significant repairs to the standard: it can't just fail to say which bindings are affected if the answer is not 'all of them'.

This is just a really interesting case by the way!

--tim


> On 14 Apr 2023, at 22:33, Shannon Spires <svs at bearlanding.com> wrote:
> 
> Tim's example is very interesting. Let's look at two forms seem like they should do the same thing, i.e. just funcall the c value.
> 
> FORM A:
> (funcall
>  (let (c)
>    (let* ((x 1)
>           (x (progn (setf c (lambda () x)) 2)))
>      (declare (special x))
>      (values c (lambda () x)))))
> 
> FORM B:
> (funcall
>  (let (c)
>    (let ((x 1))
>      (let ((x (progn (setf c (lambda () x)) 2)))
>        (declare (special x))
>        (values c (lambda () x))))))
> 
> Form B is just Form A reexpressed as nested lets rather than a single let*.
> 
> What's interesting is that CCL and Lispworks throw an error (unbound variable x) on Form A but return 1 on Form B.
> SBCL returns 1 on both, without any error.
> 
> I don't know which implementation should be considered "correct."
> 
> -SS
> 
>> On 4/14/23 3:01 PM, Tim Bradshaw wrote:
>> I think this is surprisingly underspecified.  I think the only sane answer is that declarations should apply to all the bindings of a given name in a given let* (or other sequential-binding) form.
>> 
>> It is possible to check this :
>> 
>> (let (c)
>>   (let ((x 1)
>>         (x (progn (setf c (lambda () x)) 2))
>>     (declare (special x))
>>     (values c (lambda () x))))
>> 
>> (sorry for paren/indentation errors, I'm typing this on a phone).  If the special declaration applies to both bindings then calling either function returned will be an error.  If it applies to only one: which, and why, and why does nothing say?  Either the spec simply omits this crucial information which would be a horrible omission, or the declarations apply to all the bindings.  Or, quite possibly I've just missed the place where it *does* say...
>> 
>> --tim
>> 
>>>> On 14 Apr 2023, at 21:17, Arthur Cater <arthur.cater at ucd.ie> wrote:
>>> 
>>> I can only find a define-compiler-macro, I want to see how LET* handle declarations.
>>> It surprises me that it is apparently legal to say
>>> 
>>> ? (let* ((it 7) (it (list it it)) (it (length it))) it)
>>> 2
>>> ?
>>> 
>>> and I wondered how declarations (if present) are treated - but I can’t find the source code.
>>> 
>>> TIA for any hep
> 


More information about the Openmcl-devel mailing list