GNU bug report logs - #62287
Ungexp inside vector problem

Previous Next

Package: guix;

Reported by: Andrew Tropin <andrew <at> trop.in>

Date: Mon, 20 Mar 2023 05:51:02 UTC

Severity: normal

To reply to this bug, email your comments to 62287 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-guix <at> gnu.org:
bug#62287; Package guix. (Mon, 20 Mar 2023 05:51:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Andrew Tropin <andrew <at> trop.in>:
New bug report received and forwarded. Copy sent to bug-guix <at> gnu.org. (Mon, 20 Mar 2023 05:51:02 GMT) Full text and rfc822 format available.

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

From: Andrew Tropin <andrew <at> trop.in>
To: bug-guix <at> gnu.org
Subject: Ungexp inside vector problem
Date: Mon, 20 Mar 2023 09:49:39 +0400
[Message part 1 (text/plain, inline)]
I would expect two last expressions return the same result, but the
former one doesn't do ungexp:

--8<---------------cut here---------------start------------->8---
(define a '(3 4))

(define b `#(1 2 ,a))

(eval-with-store
 #~(list '(1 2 #$a))) ;; => ((1 2 (3 4)))

(eval-with-store
 #~(list #(1 2 #$a))) ;; => (#(1 2 (ungexp a)))

(eval-with-store
 #~(list #$b)) ;; => (#(1 2 4))
--8<---------------cut here---------------end--------------->8---

Am I doing/expecting something wrong or there is a bug here?

-- 
Best regards,
Andrew Tropin
[signature.asc (application/pgp-signature, inline)]

Information forwarded to bug-guix <at> gnu.org:
bug#62287; Package guix. (Mon, 20 Mar 2023 10:46:02 GMT) Full text and rfc822 format available.

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

From: Josselin Poiret <dev <at> jpoiret.xyz>
To: Andrew Tropin <andrew <at> trop.in>, 62287 <at> debbugs.gnu.org
Subject: Re: bug#62287: Ungexp inside vector problem
Date: Mon, 20 Mar 2023 11:45:11 +0100
[Message part 1 (text/plain, inline)]
Hi Andrew,

Andrew Tropin <andrew <at> trop.in> writes:

> I would expect two last expressions return the same result, but the
> former one doesn't do ungexp:
>
> --8<---------------cut here---------------start------------->8---
> (define a '(3 4))
>
> (define b `#(1 2 ,a))
>
> (eval-with-store
>  #~(list '(1 2 #$a))) ;; => ((1 2 (3 4)))
>
> (eval-with-store
>  #~(list #(1 2 #$a))) ;; => (#(1 2 (ungexp a)))
>
> (eval-with-store
>  #~(list #$b)) ;; => (#(1 2 4))
> --8<---------------cut here---------------end--------------->8---
>
> Am I doing/expecting something wrong or there is a bug here?

It's more related to how the guile reader works, and this is such a
corner case that I don't know whether we should fix.  Basically,
anything starting with # is a reader extension, and the next character
identifies which extension it is.  #( is the reader extension for
vectors, #~ for gexp and #$ for ungexp.

To simplify, whenever you use #~, guile will insert (gexp ...) instead,
which is a hygienic macro (not just a procedure!), that will look for
ungexps inside the expression.  That traversal is only made on cons
cells though, so it doesn't try to go through any piece of syntax that
is not a cons cell!  Since #( doesn't expand to a (vector ...)
cons-cell, the subexpression gets ignored for traversal.

This is in contrast to another reader extension, #' (for syntax), which
does expand to (syntax ...), and is thus further traversed!

You can find how both of these reader extensions operate in
<libguile/read.c>.

I guess the immediate fix is to use (vector ...) rather than #(...).  We
could also add code to the gexp traversal to also traverse vectors, but
I am not even sure if they go through the gexp->sexp dance unharmed, and
we also should in principle do that for everything that can get into a
gexp, not just vectors (eg. bytevectors).

Best,
-- 
Josselin Poiret
[signature.asc (application/pgp-signature, inline)]

Information forwarded to bug-guix <at> gnu.org:
bug#62287; Package guix. (Thu, 15 Jun 2023 02:58:01 GMT) Full text and rfc822 format available.

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

From: Andrew Tropin <andrew <at> trop.in>
To: Josselin Poiret <dev <at> jpoiret.xyz>, 62287 <at> debbugs.gnu.org
Subject: Re: bug#62287: Ungexp inside vector problem
Date: Thu, 15 Jun 2023 06:57:12 +0400
[Message part 1 (text/plain, inline)]
On 2023-03-20 11:45, Josselin Poiret wrote:

> Hi Andrew,
>
> Andrew Tropin <andrew <at> trop.in> writes:
>
>> I would expect two last expressions return the same result, but the
>> former one doesn't do ungexp:
>>
>> --8<---------------cut here---------------start------------->8---
>> (define a '(3 4))
>>
>> (define b `#(1 2 ,a))
>>
>> (eval-with-store
>>  #~(list '(1 2 #$a))) ;; => ((1 2 (3 4)))
>>
>> (eval-with-store
>>  #~(list #(1 2 #$a))) ;; => (#(1 2 (ungexp a)))
>>
>> (eval-with-store
>>  #~(list #$b)) ;; => (#(1 2 4))
>> --8<---------------cut here---------------end--------------->8---
>>
>> Am I doing/expecting something wrong or there is a bug here?
>
> It's more related to how the guile reader works, and this is such a
> corner case that I don't know whether we should fix.  Basically,
> anything starting with # is a reader extension, and the next character
> identifies which extension it is.  #( is the reader extension for
> vectors, #~ for gexp and #$ for ungexp.
>
> To simplify, whenever you use #~, guile will insert (gexp ...) instead,
> which is a hygienic macro (not just a procedure!), that will look for
> ungexps inside the expression.  That traversal is only made on cons
> cells though, so it doesn't try to go through any piece of syntax that
> is not a cons cell!  Since #( doesn't expand to a (vector ...)
> cons-cell, the subexpression gets ignored for traversal.
>
> This is in contrast to another reader extension, #' (for syntax), which
> does expand to (syntax ...), and is thus further traversed!
>
> You can find how both of these reader extensions operate in
> <libguile/read.c>.
>
> I guess the immediate fix is to use (vector ...) rather than #(...).  We
> could also add code to the gexp traversal to also traverse vectors, but
> I am not even sure if they go through the gexp->sexp dance unharmed, and
> we also should in principle do that for everything that can get into a
> gexp, not just vectors (eg. bytevectors).
>

Thank you very much for extensive explanation!  I have a few tasks
related to the guile reader extensions, so when I get my hands dirty
with it, I'll probably share my new thoughts and opinions on this topic.

-- 
Best regards,
Andrew Tropin
[signature.asc (application/pgp-signature, inline)]

This bug report was last modified 309 days ago.

Previous Next


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