From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp12.migadu.com ([2001:41d0:306:f42::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms0.migadu.com with LMTPS id KHxfBoAIymGEZAEAgWs5BA (envelope-from ) for ; Mon, 27 Dec 2021 19:40:00 +0100 Received: from aspmx1.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp12.migadu.com with LMTPS id WFUOA4AIymFZBQEAauVa8A (envelope-from ) for ; Mon, 27 Dec 2021 19:40:00 +0100 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 7ECC5A29F for ; Mon, 27 Dec 2021 19:39:59 +0100 (CET) Received: from localhost ([::1]:47200 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1n1uuc-0004AD-Ny for larch@yhetil.org; Mon, 27 Dec 2021 13:39:58 -0500 Received: from eggs.gnu.org ([209.51.188.92]:53612) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1n1uti-0004A3-5R for bug-guix@gnu.org; Mon, 27 Dec 2021 13:39:02 -0500 Received: from debbugs.gnu.org ([209.51.188.43]:60957) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1n1uth-0005so-Ri for bug-guix@gnu.org; Mon, 27 Dec 2021 13:39:01 -0500 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1n1uth-0004eM-Jl for bug-guix@gnu.org; Mon, 27 Dec 2021 13:39:01 -0500 X-Loop: help-debbugs@gnu.org Subject: bug#52749: G-expressions don't consistently preserve #nil Resent-From: Philip McGrath Original-Sender: "Debbugs-submit" Resent-CC: bug-guix@gnu.org Resent-Date: Mon, 27 Dec 2021 18:39:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 52749 X-GNU-PR-Package: guix X-GNU-PR-Keywords: To: Maxime Devos , 52749@debbugs.gnu.org Received: via spool by 52749-submit@debbugs.gnu.org id=B52749.164063033217856 (code B ref 52749); Mon, 27 Dec 2021 18:39:01 +0000 Received: (at 52749) by debbugs.gnu.org; 27 Dec 2021 18:38:52 +0000 Received: from localhost ([127.0.0.1]:44270 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1n1utY-0004dw-4D for submit@debbugs.gnu.org; Mon, 27 Dec 2021 13:38:52 -0500 Received: from mail-ua1-f49.google.com ([209.85.222.49]:37464) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1n1utV-0004dd-Cg for 52749@debbugs.gnu.org; Mon, 27 Dec 2021 13:38:51 -0500 Received: by mail-ua1-f49.google.com with SMTP id o1so28293920uap.4 for <52749@debbugs.gnu.org>; Mon, 27 Dec 2021 10:38:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=philipmcgrath.com; s=google; h=message-id:date:mime-version:user-agent:subject:content-language:to :references:from:in-reply-to:content-transfer-encoding; bh=zTuuh5FQuPqoEVX7UROaNCwa0EzUTPl2Nf/0XY3wH+8=; b=jDbFitEBPE4BAIetYCOaKVTYQIRnL2RIHsjqD6xJHjhc9+76ujO6Y1MzTMYWm5yqgl O3ObsXSClRhR2IqPZQObonnby4hyT3e2qeEEjAR/QER+DlCZcst7oQ/DR3JyFkXBpPCC 5k9LTCno1R14XIRppSe7PhZza6X/DxSdLM22eZ8CcHF1f1J5tqG78+Yu6EdrlWVZF87o HYIs9QzX6uzVWCRS/+pj9TCTFnwX5MQK7YdF9oW2r4/kUe+k+Fw0s7H5InRNebUNADUG gwDZE+dDK7DyWSB9WEl4iEbLft/gq48BiYvmx2iQ74KSg9W+DuXDcL9G7cMszRZLQdbY vf+g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:date:mime-version:user-agent:subject :content-language:to:references:from:in-reply-to :content-transfer-encoding; bh=zTuuh5FQuPqoEVX7UROaNCwa0EzUTPl2Nf/0XY3wH+8=; b=ZcSBm6djdXVeHhb9wCfMBRYLJ8zOcGOZAJGoWUzh2yIMCRSo3UZk8E0HIzJUaEHzaq z5rVi8oKhJbK/ZWn5+DdOKNDHVuvpRwKiuKVz7J4m6dkpNuqkuaDhvcb1WcmC4MrMUQV xLL7+vYVcKQiuchlt7q8AJku0VZjEMtOGnIng5SrsXkV4veMFuJDd2pzFqUF//mWtQvj RA5BU2Sf86u7n7jyMrXiGttbJWPN8VNspX5tIhYbYi00V+7aqAgp0OlIQlRT5hNWqykM XmjAImgWiPfOYSNnJGLl65bCi6Y8X+JXVbvr5dB2od9T1kEQy5s5GR3Ceyx08gj/R618 mnMg== X-Gm-Message-State: AOAM531v+gk2Zy3c9r6K9hOLNqdKIdVK1TR1vUYvwSWe+yPEDWactY1M To2LeyMXHa2vZnINBQnC4tNcL/kO+efcJVIh X-Google-Smtp-Source: ABdhPJyW7OwfH6AaQYKc+Y4uTESOwfSs/m+si22RX3Fy/MdCd450Db6/B+iORndw19KknHs0jndXGw== X-Received: by 2002:a05:6102:3f4e:: with SMTP id l14mr4959945vsv.2.1640630323674; Mon, 27 Dec 2021 10:38:43 -0800 (PST) Received: from [192.168.45.37] (c-73-125-89-242.hsd1.fl.comcast.net. [73.125.89.242]) by smtp.gmail.com with ESMTPSA id l125sm3135988vke.40.2021.12.27.10.38.43 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 27 Dec 2021 10:38:43 -0800 (PST) Message-ID: Date: Mon, 27 Dec 2021 13:38:42 -0500 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.3.1 Content-Language: en-US References: <23d2ac1d-737d-787c-5535-c816566461dd@philipmcgrath.com> <6211bc6e48fa8f5dcf8711bba186812f3a5e52c4.camel@telenet.be> <637bb8909bd524ce239d66cc73d1e5ad43ce2ea9.camel@telenet.be> From: Philip McGrath In-Reply-To: <637bb8909bd524ce239d66cc73d1e5ad43ce2ea9.camel@telenet.be> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-guix@gnu.org List-Id: Bug reports for GNU Guix List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-guix-bounces+larch=yhetil.org@gnu.org Sender: "bug-Guix" X-Migadu-Flow: FLOW_IN X-Migadu-Country: US ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1640630399; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding:resent-cc: resent-from:resent-sender:resent-message-id:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post:dkim-signature; bh=zTuuh5FQuPqoEVX7UROaNCwa0EzUTPl2Nf/0XY3wH+8=; b=qfyjRdcrOmNzKvdKo+VJvH5cGfZAsQgIzHjiwjuHJJR4FRXHxsIVnNFmY8omgn8ZUIESBM GwE5QFBEZeZa7KFcwrlRh/5a2CULii7gje4/1jgT3x0VcKy9Zxq2Jgi6BAl3MO9dgYDyhb jXa8+MTpXGiTlZDP3UbqjkaW73xKudGHFz+i3g76FribQjDuevvXfT9Lj7sELVSyco6X71 FXge4bztk9iv3TLn/IdBM/zGjDPkOD3SyzrRyU+g2+Q+HxWPK1RPCTFFUQkMmsTKiBLvUf tI8HfiPeF415osjRtrLC9L7y5V+xh7ATQlYv1LZqARl/ltnIpv817BRi+yxIaA== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1640630399; a=rsa-sha256; cv=none; b=m3WQyfaoyvPOpJ/OEuZHTyK6WLNX67PvZE1Z/Xmtf8vAYsPd4/4M/YRloxferpnXKFLd5v 8e16GQtvvoygseolRPLhoTJXk80b9Xo6EDdtX4WH5wQgHB7usW2nELpXmtQCKrfCvpbDgq ujTMDvC+ppWeFMiqqwLe17l6CXXvGGzqFSfVd9yFLO1c3sQOpixliPFWVSojHaz7M3RikN L0c8uEvBD2LLLk97rRURKW+saRoMD7JGsr41RXxHELBzBTQJroMeFVcqtXPcSamMktwNYC PfrxUKbV2jwEVeAM3NSACoDLtEPNrq4oCe3+Tyj8VVRGE6acmmjB9gfPE38L+A== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=philipmcgrath.com header.s=google header.b=jDbFitEB; dmarc=none; spf=pass (aspmx1.migadu.com: domain of "bug-guix-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="bug-guix-bounces+larch=yhetil.org@gnu.org" X-Migadu-Spam-Score: -2.07 Authentication-Results: aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=philipmcgrath.com header.s=google header.b=jDbFitEB; dmarc=none; spf=pass (aspmx1.migadu.com: domain of "bug-guix-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="bug-guix-bounces+larch=yhetil.org@gnu.org" X-Migadu-Queue-Id: 7ECC5A29F X-Spam-Score: -2.07 X-Migadu-Scanner: scn1.migadu.com X-TUID: 5eyAuaH8yipb Hi! Just as a general disclaimer, I'm a Racketeer and only incidentally a Schemer, so I'm not very familiar with the universe of Guile libraries. On 12/23/21 01:59, Maxime Devos wrote: > Philip McGrath schreef op wo 22-12-2021 om 23:25 [-0500]: >> G-expressions currently do not consistently preserve the distinction >> between #nil and '(), which causes trouble for programs that rely on >> that distinction. In particular, the issue affects programs that use >> (guix build json), because that library uses #nil to represent the JSON >> value `null', whereas it uses '() to represent an empty JSON array. > > The constant #nil is only for elisp compatibility and not something > supposed to be used in Scheme code that isn't for Scheme/elisp > compatibility, so this seems more a bug in (guix build json) to me. That was not the impression I had gotten from `info "(guile)Nil"`. For example, I think someone who wanted to finish the implementation described in `info "(guile)ECMAScript"` might want to use #nil for one of the false-y ECMAScript values to take advantages of the documented efficiencies in its bit-level representation. More concretely, guile-json@1 and guile-json@3 use #nil in the same way as (guix build json). On 12/23/21 12:58, Maxime Devos wrote: > Philip McGrath schreef op wo 22-12-2021 om 23:25 [-0500]: >> G-expressions currently do not consistently preserve the distinction >> between #nil and '(), which causes trouble for programs that rely on >> that distinction. In particular, the issue affects programs that use >> (guix build json), because that library uses #nil to represent the JSON >> value `null', whereas it uses '() to represent an empty JSON array. >> >> The following program exposes the error: >> [ >> ;...] >> >> ; This one fails! >> (check-equal? (gexp->json-string #~'(@ ("k" . #nil))) >> "{\"k\":null}" >> "gexp: null in object") > > A simpler test: > > Compare this: > (cdr (gexp->approximate-sexp #~("stuff" . #nil))) > ; output: #nil --- seems like everything is ok? > > with: > (gexp->approximate-sexp #~("stuff" . #nil)) > ; output: ("stuff") --- where did the #nil go? > > I think the idea is that, if you construct a list (a b c . #nil) > in elisp, and pass it to Scheme, then Scheme should treat it as a > Scheme list, so it should be printed as (a b c) when using Scheme's > 'write' or 'display'. Since `write` and `list?` are specified by various Scheme standards, I think it is the correct choice for `write` to use a Scheme-compatible external representation for values recognized by `list?`, at least by default. (Perhaps a parameter could control this behavior?) I think the behavior of `gexp->approximate-sexp` is at least defensible, since its documentation (`info guix "gexp->approximate-sexp"`) warns that "some information can be lost". But I think the implementation of G-expressions faces more stringent obligations. I see it as analogous to the implementation of syntax objects, a macro expander, or a compiler, in that it should have a semantics-preserving representation of arbitrary Guile code, including Guile's extensions to Scheme. (I haven't yet understood at a theoretical level how "strata" and "staging" relate to the more familiar concept of "phases", but my intuition is that, while the R6RS model of phases wouldn't be enough, it seems like would probably to express staging/strata in terms of phases with Racket enhancements like the label phase level and arbitrary submodule-implemented phases.) So, I agree that: On 12/25/21 06:13, Maxime Devos wrote: > That said, it would be less surprising if the #nil/() distinction is > preserved by gexp->derivation and friends. This can be done by writing > our own 'write' procedure. Downside: it might be less efficient than > Guile's write which is implemented in C. Can be resolved by writing our > own 'write' procedure in C. I haven't looked at the implementation at all, but extending `write` certainly would be a reasonable option, and, longer-term, it might be possible to upstream a patch adding the needed behavior. A more radical option could be to use a format other than plain-text s-expressions for compiled G-expressions. For example, Racket has a forward-compatible "fast-load serialization" binary format for the kinds of values that can be embedded in compiled code.[0] There are obvious disadvantages to a binary format, but advantages include the ability to preserve source-location information and to avoid some the quirks that come with functions like `write` and `read`, for historical reasons or for the convenience of humans writing code directly. The implementation is in Racket, so it should be fairly easy to port to Guile, if that were wanted.[1] Or maybe there's something related to Guile bytecode that would work, or maybe just making a `#nil`-preserving version of `write` would be easier. -Philip [0]: https://docs.racket-lang.org/reference/fasl.html [1]: https://github.com/racket/racket/blob/master/racket/collects/racket/fasl.rkt