bug#68413: Ungexp doesn't work on deep lists
Hi, I've been using G-expressions for some time and have always been hindered by `ungexp` not working on deeper lists. For instance, when I want to embed in a G-expression a list of packages, it works >(define packages (list coreutils gnu-make ...)) > > #~(for-each >(lambda (f) > ... do-something) >'#$packages) But as soon as I use an object in which the file-like objects are deeper, it fails > (define packages > (list > (cons "coreutils" coreutils) > (cons "make" gnu-make) > ...)) > > #~(for-each >(lambda (f) > ... do-something) >'#$packages) If I send a patch to "fix" this, will it be usefull or is there a reason for this behavior? Thanks.
bug#68413: Ungexp doesn't work on deep lists
Hi Justin, Justin Veilleux writes: >> (define packages >> (list >> (cons "coreutils" coreutils) >> (cons "make" gnu-make) >> ...)) >> >> #~(for-each >>(lambda (f) >> ... do-something) >>'#$packages) > > If I send a patch to "fix" this, will it be usefull or is there a reason > for this behavior? I think IMO that it's a bug, but it's also quite tricky to properly traverse deep structures like this. The bug comes from the fact that in gexp->sexp, we traverse lists by matching the reference with (refs ...), but that doesn't match if the reference is a pair instead. Then, it tries to match with ($ (? self-quoting? x)), which does match since self-quoting? apparently returns #t on a pair, whether or not its constituents are also self-quoting. Best, -- Josselin Poiret signature.asc Description: PGP signature
bug#68413: Ungexp doesn't work on deep lists
Hi, Josselin Poiret skribis: > Justin Veilleux writes: > >>> (define packages >>> (list >>> (cons "coreutils" coreutils) >>> (cons "make" gnu-make) >>> ...)) >>> >>> #~(for-each >>>(lambda (f) >>> ... do-something) >>>'#$packages) >> >> If I send a patch to "fix" this, will it be usefull or is there a reason >> for this behavior? > > I think IMO that it's a bug, but it's also quite tricky to properly > traverse deep structures like this. The bug comes from the fact that in > gexp->sexp, we traverse lists by matching the reference with (refs ...), > but that doesn't match if the reference is a pair instead. Then, it > tries to match with ($ (? self-quoting? x)), which does > match since self-quoting? apparently returns #t on a pair, whether or > not its constituents are also self-quoting. Actually, what bug are we talking about? It seems to work for me with this example: --8<---cut here---start->8--- scheme@(guile-user)> (define packages `(("coreutils" ,coreutils) ("make" ,gnu-make))) scheme@(guile-user)> ,build (scheme-file "foo" #~(begin '#$packages)) building /gnu/store/lq9gvbilv0y2nph00zxk6bn3lvcgdxqq-foo.drv... $7 = "/gnu/store/9ryh6v80jvjv3kwx0q782h26h9gbaclj-foo" scheme@(guile-user)> (call-with-input-file $7 get-string-all) $8 = "(begin (quote ((\"coreutils\" \"/gnu/store/mppp9hwxizx9g9pikwcvvshb2ffxyq7p-coreutils-9.1\") (\"make\" \"/gnu/store/9fadhs5qmwl5x7f669a0v39b3ryrmmf1-make-4.3\"" --8<---cut here---end--->8--- One of the design decisions for gexps was to ensure that substituting a file-like object by its file name would be O(1) in most cases. Substitution in lists as in the example above is supported, but primarily for backward compatibility. It should be avoided when possible because it’s inefficient: ‘gexp->sexp’ needs to traverse the whole list/tree in search of potential candidates. Thanks, Ludo’.
bug#68413: Ungexp doesn't work on deep lists
Hi Ludo, Ludovic Courtès writes: > Actually, what bug are we talking about? It seems to work for me with > this example: > > --8<---cut here---start->8--- > scheme@(guile-user)> (define packages `(("coreutils" ,coreutils) ("make" > ,gnu-make))) > scheme@(guile-user)> ,build (scheme-file "foo" #~(begin '#$packages)) > building /gnu/store/lq9gvbilv0y2nph00zxk6bn3lvcgdxqq-foo.drv... > $7 = "/gnu/store/9ryh6v80jvjv3kwx0q782h26h9gbaclj-foo" > scheme@(guile-user)> (call-with-input-file $7 get-string-all) > $8 = "(begin (quote ((\"coreutils\" > \"/gnu/store/mppp9hwxizx9g9pikwcvvshb2ffxyq7p-coreutils-9.1\") (\"make\" > \"/gnu/store/9fadhs5qmwl5x7f669a0v39b3ryrmmf1-make-4.3\"" > --8<---cut here---end--->8--- > > One of the design decisions for gexps was to ensure that substituting a > file-like object by its file name would be O(1) in most cases. > > Substitution in lists as in the example above is supported, but > primarily for backward compatibility. It should be avoided when > possible because it’s inefficient: ‘gexp->sexp’ needs to traverse the > whole list/tree in search of potential candidates. Notice that OP's example uses `(("thing" . ,package)), ie. lists of pairs and not lists of lists, as in your case! Best, -- Josselin Poiret signature.asc Description: PGP signature