GNU bug report logs - #14164
letrec: detect illegal accesses to vars before entering body

Previous Next

Package: guile;

Reported by: Nikita Karetnikov <nikita <at> karetnikov.org>

Date: Tue, 9 Apr 2013 04:43:02 UTC

Severity: wishlist

To reply to this bug, email your comments to 14164 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-guile <at> gnu.org:
bug#14164; Package guile. (Tue, 09 Apr 2013 04:43:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Nikita Karetnikov <nikita <at> karetnikov.org>:
New bug report received and forwarded. Copy sent to bug-guile <at> gnu.org. (Tue, 09 Apr 2013 04:43:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Nikita Karetnikov <nikita <at> karetnikov.org>
To: bug-guile <at> gnu.org
Subject: 'letrec' allows to refer to the values of previously bound variables
Date: Tue, 09 Apr 2013 08:41:04 +0400
[Message part 1 (text/plain, inline)]
According to the manual [1], this snippet:

(letrec ((a 42)
         (b (+ a 10)))
  (* a b))

should return "Error: unbound variable: a."  But it returns 2184 in
Guile 2.0.7.  Either there is a bug in the manual or 'letrec' doesn't
work properly.

[1] https://gnu.org/software/guile/manual/guile.html#Local-Bindings
[Message part 2 (application/pgp-signature, inline)]

Changed bug title to 'letrec: detect illegal accesses to vars before entering body' from ''letrec' allows to refer to the values of previously bound variables' Request was from Mark H Weaver <mhw <at> netris.org> to control <at> debbugs.gnu.org. (Tue, 09 Apr 2013 05:17:01 GMT) Full text and rfc822 format available.

Severity set to 'wishlist' from 'normal' Request was from Mark H Weaver <mhw <at> netris.org> to control <at> debbugs.gnu.org. (Tue, 09 Apr 2013 05:17:01 GMT) Full text and rfc822 format available.

Information forwarded to bug-guile <at> gnu.org:
bug#14164; Package guile. (Tue, 09 Apr 2013 05:19:02 GMT) Full text and rfc822 format available.

Message #12 received at 14164 <at> debbugs.gnu.org (full text, mbox):

From: Mark H Weaver <mhw <at> netris.org>
To: Nikita Karetnikov <nikita <at> karetnikov.org>
Cc: 14164 <at> debbugs.gnu.org
Subject: Re: bug#14164: letrec: detect illegal accesses to vars before
	entering body
Date: Tue, 09 Apr 2013 01:14:58 -0400
Nikita Karetnikov <nikita <at> karetnikov.org> writes:

> According to the manual [1], this snippet:
>
> (letrec ((a 42)
>          (b (+ a 10)))
>   (* a b))
>
> should return "Error: unbound variable: a."

The manual doesn't say anything nearly that specific.  It says "Note
that while the init expressions may refer to the new variables, they may
not access their values."  The R5RS says "it must be possible to
evaluate each <init> without assigning or referring to the value of any
<variable>.  If this restriction is violated, then it is an error."

In general, if the manual says you "may not" do something, or if the
R5RS says "it is an error", that means that if you do, the results are
unspecified.  It does not constitute a promise to report an error if you
do.

I agree that we should ideally report errors such as this, but this is
not a bug, but rather a wishlist item.  Note that generating code that
detects programmer errors such as this may carry a non-trivial runtime
cost, so we might need to provide a distinct compilation mode that
inserts such debugging checks.

This is on my TODO list, but I wouldn't hold your breath :)

    Regards,
      Mark




Information forwarded to bug-guile <at> gnu.org:
bug#14164; Package guile. (Tue, 09 Apr 2013 06:39:01 GMT) Full text and rfc822 format available.

Message #15 received at 14164 <at> debbugs.gnu.org (full text, mbox):

From: Nikita Karetnikov <nikita <at> karetnikov.org>
To: Mark H Weaver <mhw <at> netris.org>
Cc: 14164 <at> debbugs.gnu.org
Subject: Re: bug#14164: letrec: detect illegal accesses to vars before
	entering body
Date: Tue, 09 Apr 2013 10:37:38 +0400
[Message part 1 (text/plain, inline)]
>> According to the manual [1], this snippet:
>>
>> (letrec ((a 42)
>>          (b (+ a 10)))
>>   (* a b))
>>
>> should return "Error: unbound variable: a."

> The manual doesn't say anything nearly that specific.

Either you missed it or I misunderstood this sentence.  So if you missed
it, it can be found below 'syntax: letrec* bindings body'.

> In general, if the manual says you "may not" do something, or if the
> R5RS says "it is an error", that means that if you do, the results are
> unspecified.

Are you talking about the result of 'letrec' or 'b'?  Anyway, why does
it return 2184 if the results are unspecified?  Could you elaborate?
[Message part 2 (application/pgp-signature, inline)]

Information forwarded to bug-guile <at> gnu.org:
bug#14164; Package guile. (Tue, 09 Apr 2013 16:49:02 GMT) Full text and rfc822 format available.

Message #18 received at 14164 <at> debbugs.gnu.org (full text, mbox):

From: Mark H Weaver <mhw <at> netris.org>
To: Nikita Karetnikov <nikita <at> karetnikov.org>
Cc: 14164 <at> debbugs.gnu.org
Subject: Re: bug#14164: letrec: detect illegal accesses to vars before
	entering body
Date: Tue, 09 Apr 2013 12:44:07 -0400
Nikita Karetnikov <nikita <at> karetnikov.org> writes:

>>> According to the manual [1], this snippet:
>>>
>>> (letrec ((a 42)
>>>          (b (+ a 10)))
>>>   (* a b))
>>>
>>> should return "Error: unbound variable: a."
>
>> The manual doesn't say anything nearly that specific.
>
> Either you missed it or I misunderstood this sentence.  So if you missed
> it, it can be found below 'syntax: letrec* bindings body'.

Oops!  You're right, of course.  Apologies for saying you were wrong.
I'll fix the manual.

>> In general, if the manual says you "may not" do something, or if the
>> R5RS says "it is an error", that means that if you do, the results are
>> unspecified.
>
> Are you talking about the result of 'letrec' or 'b'?  Anyway, why does
> it return 2184 if the results are unspecified?  Could you elaborate?

Well, first of all, I misspoke.  In this case, I should have said (as
the R5RS did) that "it is an error", which in Scheme-standard-speak
means "anything at all could happen".  This is different from "an error
is signaled" or "an error is raised" or "an exception is thrown" which
consitutes a promise to report an error.

When the standard (or the manual) says "the result is unspecified", that
means that some value will be returned, but that value could be
anything.

Although Guile includes a distinguished value shown as "*unspecified*",
which is often used in these cases, it is not always used.  In practice,
we use it when we can easily do so without imposing a runtime cost, as a
debugging aid.  However, it is not always used.

     Thanks,
       Mark




Information forwarded to bug-guile <at> gnu.org:
bug#14164; Package guile. (Tue, 09 Apr 2013 17:25:02 GMT) Full text and rfc822 format available.

Message #21 received at 14164 <at> debbugs.gnu.org (full text, mbox):

From: Nikita Karetnikov <nikita <at> karetnikov.org>
To: Mark H Weaver <mhw <at> netris.org>
Cc: 14164 <at> debbugs.gnu.org
Subject: Re: bug#14164: letrec: detect illegal accesses to vars before
	entering body
Date: Tue, 09 Apr 2013 21:22:51 +0400
[Message part 1 (text/plain, inline)]
> I'll fix the manual.

Thanks.

So what's the difference between 'letrec' and 'letrec*', then?  I fail
to grasp it.  Could you add a relevant example to the manual?

> When the standard (or the manual) says "the result is unspecified", that
> means that some value will be returned, but that value could be
> anything.

Just to clarify: When the standard says "unspecified," I can read it as
"it's up to the particular implementation (e.g., Guile)," right?
[Message part 2 (application/pgp-signature, inline)]

Information forwarded to bug-guile <at> gnu.org:
bug#14164; Package guile. (Wed, 10 Apr 2013 09:30:03 GMT) Full text and rfc822 format available.

Message #24 received at 14164 <at> debbugs.gnu.org (full text, mbox):

From: Mark H Weaver <mhw <at> netris.org>
To: Nikita Karetnikov <nikita <at> karetnikov.org>
Cc: 14164 <at> debbugs.gnu.org
Subject: Re: bug#14164: letrec: detect illegal accesses to vars before
	entering body
Date: Wed, 10 Apr 2013 05:25:20 -0400
Nikita Karetnikov <nikita <at> karetnikov.org> writes:

>> I'll fix the manual.
>
> Thanks.
>
> So what's the difference between 'letrec' and 'letrec*', then?  I fail
> to grasp it.

The difference is that in 'letrec*', the initializers are guaranteed to
be evaluated in order, and they are allowed to access earlier bindings
before entering the body.  In 'letrec', the order in which the
initializers are evaluated is unspecified, and they are *not* allowed to
access earlier bindings.

> Could you add a relevant example to the manual?

The example given in the manual under 'letrec*' was basically correct.
The only problem was that it shouldn't have claimed that an error would
be reported to the user.

Here's the change I made to the manual:

--8<---------------cut here---------------start------------->8---
index 5763f36..e3a9918 100644 (file)
--- a/doc/ref/api-binding.texi
+++ b/doc/ref/api-binding.texi
@@ -218,9 +218,9 @@ variables.
 
 @lisp
 (letrec ((a 42)
-         (b (+ a 10)))
+         (b (+ a 10)))  ;; Illegal access
   (* a b))
-@result{} ;; Error: unbound variable: a
+;; The behavior of the expression above is unspecified
 
 (letrec* ((a 42)
           (b (+ a 10)))
  (* a b))
@result{} 2184
@end lisp
--8<---------------cut here---------------end--------------->8---

>> When the standard (or the manual) says "the result is unspecified", that
>> means that some value will be returned, but that value could be
>> anything.
>
> Just to clarify: When the standard says "unspecified," I can read it as
> "it's up to the particular implementation (e.g., Guile)," right?

Yes, but keep in mind that there's no guarantee that the results will be
consistent from one evaluation to the next, even within a particular
implementation.  For example, the 'letrec' above could return a random
number each time it is run, or even crash randomly, though that would
clearly be undesirable and we would seek to avoid that in Guile.

     Regards,
       Mark




Information forwarded to bug-guile <at> gnu.org:
bug#14164; Package guile. (Fri, 12 Apr 2013 08:48:02 GMT) Full text and rfc822 format available.

Message #27 received at 14164 <at> debbugs.gnu.org (full text, mbox):

From: ludo <at> gnu.org (Ludovic Courtès)
To: Mark H Weaver <mhw <at> netris.org>
Cc: 14164 <at> debbugs.gnu.org
Subject: Re: bug#14164: letrec: detect illegal accesses to vars before
	entering body
Date: Fri, 12 Apr 2013 10:43:08 +0200
Mark H Weaver <mhw <at> netris.org> skribis:

>  @lisp
>  (letrec ((a 42)
> -         (b (+ a 10)))
> +         (b (+ a 10)))  ;; Illegal access
>    (* a b))

Please change it to “invalid access”.  Nothing illegal here.  ;-)

Ludo’.




This bug report was last modified 12 years and 65 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.