Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

declaring 'ignore' inside a loop using destructuring

7 views
Skip to first unread message

Kyle M

unread,
Nov 24, 2009, 9:28:38 AM11/24/09
to
Here's a question for the loopers. Say I'm using loop destructuring
like this:

(defun foo (some-list)
(loop for (a b c) in some-list
do ;; code that uses a and c, but not b:
(print a) (print c)))

(compile 'foo) -> Warning: Variable b is never used.

I know that in a destructuring-bind or a multivalue-bind you can just
throw a (declare (ignore b)) in there. Is there any way to ignore this
variable?

I'm using Allegro CL in case yer wondering.

Kyle

Kenneth Tilton

unread,
Nov 24, 2009, 9:33:29 AM11/24/09
to
Kyle M wrote:
> Here's a question for the loopers. Say I'm using loop destructuring
> like this:
>
> (defun foo (some-list)
> (loop for (a b c) in some-list
> do ;; code that uses a and c, but not b:
> (print a) (print c)))
>
> (compile 'foo) -> Warning: Variable b is never used.
>
> I know that in a destructuring-bind or a multivalue-bind you can just
> throw a (declare (ignore b)) in there. Is there any way to ignore this
> variable?

It's kinda weird:

(loop for (a nil c)....

Same as for destructuring-bind, btw.

kt

Kyle M

unread,
Nov 24, 2009, 10:00:54 AM11/24/09
to


Thanks. That helps, although I'm a little annoyed by that.

Partially because it looks weird. Although most of my code looks
weird, so that's not a huge deal.

Also, though, because I will wind up using the variable b at some
point later on, and I'd like to give it a name (a descriptive name,
not just b).

Now that I think about it I'm wondering if this is actually an
implementation issue:

(loop for x in '(1 2 3)
return 'nothing))

This will not warn me about not using x (in Allegro).

Kyle

Kenneth Tilton

unread,
Nov 24, 2009, 12:08:22 PM11/24/09
to
Kyle M wrote:
> On Nov 24, 9:33 am, Kenneth Tilton <kentil...@gmail.com> wrote:
>> Kyle M wrote:
>>> Here's a question for the loopers. Say I'm using loop destructuring
>>> like this:
>>> (defun foo (some-list)
>>> (loop for (a b c) in some-list
>>> do ;; code that uses a and c, but not b:
>>> (print a) (print c)))
>>> (compile 'foo) -> Warning: Variable b is never used.
>>> I know that in a destructuring-bind or a multivalue-bind you can just
>>> throw a (declare (ignore b)) in there. Is there any way to ignore this
>>> variable?
>> It's kinda weird:
>>
>> (loop for (a nil c)....
>>
>> Same as for destructuring-bind, btw.
>>
>> kt
>
>
> Thanks. That helps, although I'm a little annoyed by that.

It is /so/ C++! But this is loop, which is a DSL for iteration meaning
they went nuts for productivity and had fun with syntax as needed to
keep the productivity up.

If you don't like it, don't use it. Do not try to come up with a better
way, this is Lisp, you won't.

>
> Partially because it looks weird. Although most of my code looks
> weird, so that's not a huge deal.
>
> Also, though, because I will wind up using the variable b at some
> point later on, and I'd like to give it a name (a descriptive name,
> not just b).

Hunh? Did someone leave you in a strait jacket so you can't reach the
keyboard to change the nil to "bozo"? And what is wrong with "b"?

http://smuglispweeny.blogspot.com/2008/07/aa-bb-cc-and-dd.html


kt

--

http://thelaughingstockatpngs.com/
http://www.facebook.com/pages/The-Laughingstock/115923141782?ref=nf

Kyle M

unread,
Nov 24, 2009, 12:22:08 PM11/24/09
to


I like the destructuring in loop. That's one reason I use it so much.
I'm parsing a CSV file with several fields, so my code looks like

(loop for newline = (read-line is nil)
while newline
as (quarterback halfback fullback ...other stuff... )
= (delimited-string-to-list newline #\,) ;;allegro CL
do
...stuff with the quarterback and fullback...
)

Since every field in the file has some column it's associated with, I
give them variable names to remind me what those columns are. This way
when I come back later, I don't have to look it up.

Kyle

russell...@yahoo.com

unread,
Nov 24, 2009, 12:34:25 PM11/24/09
to
Kyle M <kyl...@gmail.com> writes:

> Here's a question for the loopers. Say I'm using loop destructuring
> like this:
>
> (defun foo (some-list)
> (loop for (a b c) in some-list
> do ;; code that uses a and c, but not b:
> (print a) (print c)))
>
> (compile 'foo) -> Warning: Variable b is never used.

Perhaps the obvious?

(defun foo (some-list)
(loop for (a b c) in some-list

do b
(print a) (print c)))

-russ

Tim Bradshaw

unread,
Nov 24, 2009, 3:47:37 PM11/24/09
to
On 2009-11-24 15:00:54 +0000, Kyle M <kyl...@gmail.com> said:

> Now that I think about it I'm wondering if this is actually an
> implementation issue:
>
> (loop for x in '(1 2 3)
> return 'nothing))
>
> This will not warn me about not using x (in Allegro).

I think it is, probably, not an implementation issue, but I am not sure.

For DOTIMES (for instance) it is explicitly undefined whether each
variable is rebound for each iteration or whether there is only one
binding per variable. This means it is undefined whether the variable
is ignored or not if you do not use it. Simplifying to the point of
being wrong, the difference is between something like:

(...
(let ((i ...))
...your code...))

And

(...bind i...
(locally
...your code...)
...
(incf i)
...)

In the latter case, I is *not* ignored even if your code does not use it,

For LOOP, I *think* it is clear that the expansion is more like the
second case. So the variables are not ignored, even if your code does
not use them. However I am not sure that this is required to be the
case: I think it probably is, but I'm not completely sure.

This can make huge differences for code which returns closures of course.

I can imagine implementations clever enough that they realised that no
*user* code used a binding and warned about that, even though the LOOP
expansion itself did assign to the variable.

I have used "variable" and "binding" sloppily above.

Kyle M

unread,
Nov 24, 2009, 6:24:40 PM11/24/09
to
On Nov 24, 3:47 pm, Tim Bradshaw <t...@cley.com> wrote:

I emailed Franz about it, and Steve Haflich made an interesting point
about the spec. I hope he doesn't mind my paraphrasing him.

The section on ignore/ignorable says:

"The stream variables established by with-open-file, with-open-stream,
with-input-from-string, and with-output-to-string, and all iteration
variables are, by definition, always "used". Using (declare (ignore
v)), for such a variable v has unspecified consequences."

The term iteration-variable is in the glossary, and basically includes
the variables x, y, and z in the following loop:

(loop for x in list1
for (y z) in list2
...)

So, basically, these variables are considered "used", even if they
aren't used. So the compiler should not warn me at all.

Kyle

Ron Garret

unread,
Nov 24, 2009, 6:53:46 PM11/24/09
to
In article <2009112420473716807-tfb@cleycom>,
Tim Bradshaw <t...@cley.com> wrote:

In CL, variables are bindings, so the two terms can be freely
interchanged. Where you were a little sloppy is using the term
"variable" where you meant "variable name", e.g. "it is explicitly
undefined whether each variable is rebound for each iteration".
Strictly speaking that should have been, "it is explicitly undefined
whether each variable NAME is rebound for each iteration."

rg

Kenneth Tilton

unread,
Nov 24, 2009, 9:38:42 PM11/24/09
to

Or the perhaps less obvious:

(defun frank (some-list)


(loop for (a b c) in some-list

do b do b do
(print a) (print c)))

?

Tobias C. Rittweiler

unread,
Nov 25, 2009, 2:42:30 AM11/25/09
to
Tim Bradshaw <t...@cley.com> writes:

> On 2009-11-24 15:00:54 +0000, Kyle M <kyl...@gmail.com> said:
>
>> Now that I think about it I'm wondering if this is actually an
>> implementation issue:
>>
>> (loop for x in '(1 2 3)
>> return 'nothing))
>>
>> This will not warn me about not using x (in Allegro).
>
> I think it is, probably, not an implementation issue, but I am not sure.
>
> For DOTIMES (for instance) it is explicitly undefined whether each
> variable is rebound for each iteration or whether there is only one
> binding per variable. This means it is undefined whether the variable
> is ignored or not if you do not use it.

Nope, CLHS dictionary entry for IGNORE:

The stream variables established by with-open-file, with-open-stream,
with-input-from-string, and with-output-to-string, and all iteration
variables are, by definition, always ``used''. Using (declare (ignore
v)), for such a variable v has unspecified consequences.

For understandable reasons, I don't think any implementation actually
completely adheres to that.

-T.

Tim Bradshaw

unread,
Nov 25, 2009, 3:10:39 AM11/25/09
to
On 2009-11-25 07:42:30 +0000, "Tobias C. Rittweiler"
<t...@freebits.de.invalid> said:

> Nope, CLHS dictionary entry for IGNORE:
>
> The stream variables established by with-open-file, with-open-stream,
> with-input-from-string, and with-output-to-string, and all iteration
> variables are, by definition, always ``used''. Using (declare (ignore
> v)), for such a variable v has unspecified consequences.
>
> For understandable reasons, I don't think any implementation actually
> completely adheres to that.

OK, that's interesting (and answers the question). It's hard to see
how this would work for an implementation which did rebind each time
("It is implementation-dependent whether dolist establishes a new
binding of var on each iteration or whether it establishes a binding
for var once at the beginning and then assigns it on any subsequent
iterations."): such an implementation would have to somehow secretly
"touch" the binding (or have a secret declaration that the variable was
actually used, even though it might not be).

Pascal J. Bourguignon

unread,
Nov 25, 2009, 4:20:09 AM11/25/09
to
Tim Bradshaw <t...@cley.com> writes:

Like (declare (ignorable variable)) ?


--
__Pascal Bourguignon__

Björn Lindberg

unread,
Nov 25, 2009, 4:33:54 AM11/25/09
to
Tim Bradshaw <t...@cley.com> writes:

I don't see why. The text Tobias quotes from the Hyperspec puts a
restriction on the user, but gives full freedom to the
implementation. In the case at hand, an implementation should not warn
for such variables being unused, but doing that for any variable is not
required by the spec either.


Bj�rn Lindberg

Tim Bradshaw

unread,
Nov 25, 2009, 12:21:08 PM11/25/09
to
On 2009-11-25 09:33:54 +0000, bj...@runa.se (Bj�rn Lindberg) said:

>
> I don't see why. The text Tobias quotes from the Hyperspec puts a
> restriction on the user, but gives full freedom to the
> implementation. In the case at hand, an implementation should not warn
> for such variables being unused, but doing that for any variable is not
> required by the spec either.

What I'm getting at is that it seems to be hard for an implementation
which rebinds to check for bad user declarations. Implementations do
not have to check of course, but they might want to do so to detect bad
user code.

Such an implementation would have to expand (as Pascal said) to something like

(let ((i ...)) ; or other binding form
(declare (ignorable i)) ; required to stop warnings where variable is unused
... user code ...
)

but ...user code... could start with an IGNORE declaration, so the
implementation would have to check for that (which, OK, it could do).

(And in fact I'm not sure what the effect of an IGNORABLE and IGNORE
declaration for a variable is.)

0 new messages