GNU logs - #67786, boring messages


Message sent to guix-patches@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: [bug#67786] [PATCH] doc: Add documentation for define-record-type*
Resent-From: Skyler Ferris <skyvine@HIDDEN>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: guix-patches@HIDDEN
Resent-Date: Mon, 11 Dec 2023 20:18:02 +0000
Resent-Message-ID: <handler.67786.B.17023258314339 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: report 67786
X-GNU-PR-Package: guix-patches
X-GNU-PR-Keywords: patch
To: 67786 <at> debbugs.gnu.org
Cc: Skyler Ferris <skyvine@HIDDEN>
X-Debbugs-Original-To: guix-patches@HIDDEN
Received: via spool by submit <at> debbugs.gnu.org id=B.17023258314339
          (code B ref -1); Mon, 11 Dec 2023 20:18:02 +0000
Received: (at submit) by debbugs.gnu.org; 11 Dec 2023 20:17:11 +0000
Received: from localhost ([127.0.0.1]:54730 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1rCmiE-00017u-OW
	for submit <at> debbugs.gnu.org; Mon, 11 Dec 2023 15:17:11 -0500
Received: from lists.gnu.org ([2001:470:142::17]:51852)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <skyvine@HIDDEN>) id 1rCmiC-00017f-Tj
 for submit <at> debbugs.gnu.org; Mon, 11 Dec 2023 15:17:09 -0500
Received: from eggs.gnu.org ([2001:470:142:3::10])
 by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.90_1) (envelope-from <skyvine@HIDDEN>)
 id 1rCmhr-0000I4-OO
 for guix-patches@HIDDEN; Mon, 11 Dec 2023 15:16:47 -0500
Received: from c-24-143-119-132.customer.broadstripe.net ([24.143.119.132]
 helo=localhost)
 by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.90_1) (envelope-from <skyvine@HIDDEN>)
 id 1rCmho-00009y-Tv
 for guix-patches@HIDDEN; Mon, 11 Dec 2023 15:16:47 -0500
Received: from [127.0.0.1] (helo=localhost.localdomain)
 by localhost with esmtp (Exim 4.96.1)
 (envelope-from <skyvine@HIDDEN>) id 1rCmhm-0000Kt-2P;
 Mon, 11 Dec 2023 12:16:42 -0800
From: Skyler Ferris <skyvine@HIDDEN>
Date: Mon, 11 Dec 2023 12:16:40 -0800
Message-ID: <9bf2efa9c7aab1661fcf5180d1e536fc6dc0e9b3.1702324538.git.skyvine@HIDDEN>
X-Mailer: git-send-email 2.41.0
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Received-SPF: softfail client-ip=24.143.119.132;
 envelope-from=skyvine@HIDDEN; helo=localhost
X-Spam_score_int: 72
X-Spam_score: 7.2
X-Spam_bar: +++++++
X-Spam_report: (7.2 / 5.0 requ) BAYES_00=-1.9, FREEMAIL_FROM=0.001,
 FSL_HELO_NON_FQDN_1=0.001, HELO_LOCALHOST=3.828, KHOP_HELO_FCRDNS=0.26,
 RCVD_IN_PBL=3.335, RDNS_DYNAMIC=0.982, SPF_SOFTFAIL=0.665,
 SPOOFED_FREEMAIL=0.001,
 T_SCC_BODY_TEXT_LINE=-0.01 autolearn=no autolearn_force=no
X-Spam_action: reject
X-Spam-Score: 1.0 (+)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -0.0 (/)

* doc/guix.texi: Add sections describing the typical usage and API
reference for define-record-type*

Change-Id: I19e7220553d10652c794e6e0172b2c9ee961f54f
---
 doc/contributing.texi |   1 -
 doc/guix.texi         | 274 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 274 insertions(+), 1 deletion(-)

diff --git a/doc/contributing.texi b/doc/contributing.texi
index 9e9b89782c..60fcf95b77 100644
--- a/doc/contributing.texi
+++ b/doc/contributing.texi
@@ -1311,7 +1311,6 @@ Data Types and Pattern Matching
 notably the fact that it is hard to read, error-prone, and a hindrance
 to proper type error reports.
 
-@findex define-record-type*
 @findex match-record
 @cindex pattern matching
 Guix code should define appropriate data types (for instance, using
diff --git a/doc/guix.texi b/doc/guix.texi
index 1fd2e21608..e9d0fd1466 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -12561,6 +12561,280 @@ G-Expressions
 @code{(*approximate*)}, but this may change.
 @end deffn
 
+@node Records in Guix
+@section Records in Guix
+Guix uses @code{define-record-type*} to define structures with a lispy format.
+Packages, operating systems, etc are all defined with
+@code{define-record-type*} facilities. If one was using this facility to
+define preferences for a text editor, it might look like this:
+
+@lisp
+;; The only valid emulation modes are the symbol 'emacs, the symbol 'vim, or
+;; the boolean #f. As a convenience to the user, if they pass in a string
+;; first convert it to a symbol and accept it if it is valid.
+(define (sanitize-emulation-mode value)
+  (let ((symbolized-value (cond ((not value)     #f)
+                                ((string? value) (string->symbol value))
+                                (#t              value))))
+    (unless (or (not symbolized-value)
+                (eq? symbolized-value 'emacs)
+                (eq? symbolized-value 'vim))
+      (throw 'bad-emulation-made
+             (format #f "Unrecognized emulation mode: ~s" value)))
+    symbolized-value))
+
+(define-record-type*
+  <editor-preferences> editor-preferences make-editor-preferences
+  editor-preferences? this-editor-preferences
+  (background-color editor-preferences-background-color
+                    (default "000000"))
+  (text-color       editor-preferences-text-color
+                    (default "FFFFFF"))
+  (emulation-mode   editor-preferences-emulation-mode
+                    (default #f)
+                    (sanitize sanitize-emulation-mode)))
+@end lisp
+
+A user could then define their preferences like this:
+
+@lisp
+(define my-preferences
+  (editor-preferences
+    (background-color "222222")
+    (emulation-mode   'vim)))
+@end lisp
+
+The value contained in @code{my-preferences} contains a custom
+@code{background-color} and @code{emulation-mode}, but keeps the default
+@code{text-color} (@code{"FFFFFF"}). If an invalid @code{emulation-mode} had
+been specified, for example if the user passed in @code{"vi"} instead of
+@code{"vim"}, @code{sanitize-emulation-mode} would immediately throw an error.
+
+The program can access values like this:
+
+@lisp
+(editor-preferences-background-color my-preferences)
+@result{} "222222"
+(editor-preferences-text-color my-preferences)
+@result{} "FFFFFF"
+(editor-preferences-emulation-mode my-preferences)
+@result{} 'vim
+@end lisp
+
+There is no way to define setters (all instances are immutable).
+
+@node Record Inheritance
+@subsection Record Inheritance
+It is also possible to inherit from previously defined instances when creating
+new ones. Continuing with the editor example, someone might want to base their
+preferences on their friend's preferences but customize a value:
+
+@lisp
+(define friends-preferences
+  (editor-preferences
+    (inherit my-preferences)
+    (emulation-mode 'emacs)))
+@end lisp
+
+This keeps the same @code{background-color} and @code{text-color} that are
+contained in @code{my-preferences} but changes the @code{emulation-mode} to
+be @code{'emacs} instead of @code{'vim}.
+
+Sometimes it does not make sense for a field to be inherited. Suppose that the
+@code{<editor-preferences>} type is updated to contain a username so that a
+friendly greeting can be displayed when the program starts up:
+
+@lisp
+;; Usernames must be strings. It would be strange to pass a username as a
+;; symbol, so throw an error in case the user meant to pass in a variable's
+;; value instead of a literal symbol.
+(define (sanitize-username value)
+  (unless (string? value)
+    (throw 'bad-username
+           (format #f "Usernames must be strings! Got: ~s" value)))
+  value)
+
+(define (sanitize-emulation-mode value)
+  (let ((symbolized-value (cond ((not value)     #f)
+                                ((string? value) (string->symbol value))
+                                (#t              value))))
+    (unless (or (not symbolized-value)
+                (eq? symbolized-value 'emacs)
+                (eq? symbolized-value 'vim))
+      (throw 'bad-emulation-made
+             (format #f "Unrecognized emulation mode: ~s" value)))
+    symbolized-value))
+
+(define-record-type*
+  <editor-preferences> editor-preferences make-editor-preferences
+  editor-preferences? this-editor-preferences
+  (username         editor-preferences-username
+                    (innate)
+                    (sanitize sanitize-username))
+  (background-color editor-preferences-background-color
+                    (default "000000"))
+  (text-color       editor-preferences-text-color
+                    (default "FFFFFF"))
+  (emulation-mode   editor-preferences-emulation-mode
+                    (default #f)
+                    (sanitize sanitize-emulation-mode)))
+@end lisp
+
+There are a couple of differences in the new @code{username} field compared to
+the fields we looked at earlier. It is marked as @code{innate}, which means
+that it will not be inherited. For example, consider what would happen if we
+tried to define new instances like this:
+
+@lisp
+(define my-preferences
+  (editor-preferences
+    (username         "my-username")
+    (background-color "222222")
+    (emulation-mode   'vim)))
+
+(define friends-preferences
+  (editor-preferences
+    (inherit my-preferences)
+    (emulation-mode 'emacs)))
+@end lisp
+
+While the @code{friends-preferences} instance still inherits the values for
+@code{background-color} and @code{text-color}, it will not inherit the value
+for @code{username}. Furthermore, as the @code{username} field does not define
+a default value the attempted creation of @code{friends-preferences} will
+actually throw an error. Instead, we could do this:
+
+@lisp
+(define my-preferences
+  (editor-preferences
+    (username         "my-username")
+    (background-color "222222")
+    (emulation-mode   'vim)))
+
+(define friends-preferences
+  (editor-preferences
+    (inherit        my-preferences)
+    (username       "friends-username")
+    (emulation-mode 'emacs)))
+@end lisp
+
+@node @code{define-record-type*} Reference
+@subsection @code{define-record-type*} Reference
+@defmac define-record-type* name syntactic-constructor constructor predicate this-identifier fields ...
+
+Define a new record type and associated helpers.
+
+@table @var
+@item name
+A symbol used to name the type, as would normally be provided to a plain
+@code{define-record-type} form. For example, @code{<package>}.
+
+@item syntactic-constructor
+A symbol that will be used to define the user-facing constructor. For example,
+the symbol @code{package} is the syntactic constructor for the @code{<package>}
+structure.
+
+@item constructor
+A symbol that will be used to define the traditional constructor. It is used in
+the implementation of the syntactic constructor, but will not typically be used
+elsewhere. The traditional @code{make-name} (for example, @code{make-package})
+is a fine value to use here.
+
+@item predicate
+A symbol that will be used to test if a value is an instance of this record.
+For example, @code{package?}.
+
+@item this-identifier
+This symbol can be used when defining fields that need to refer to the struct
+that contains them. For an example of this, see the @code{thunked} field
+property, below.
+
+@item fields
+A set of field specifiers which take the following form:
+
+@lisp
+(field-name field-getter properties ...)
+@end lisp
+
+Each of the properties must have one of the following forms:
+
+@table @code
+@item (default @var{value})
+Defines the default value for the field, if the user does not specify one using
+the syntactic constructor.
+
+@item (innate)
+Fields marked as innate will not be inherited from parent objects (see
+Instantiating Records, below, for details of object inheritance).
+
+@item (sanitize @var{proc})
+The value given by the user will be passed into @var{proc} before being stored
+in the object. For example, consider this struct definition:
+
+@lisp
+(define-record-type* <thing> thing make-thing
+  thing?
+  this-thing
+  (name  thing-name
+         (sanitize (lambda (value)
+                     (cond ((string? value) value)
+                           ((symbol? value) (symbol->string value))
+                           (else (throw 'bad! value)))))))
+@end lisp
+
+When creating @code{thing} instances either a string or a symbol can be
+supplied but it will always be stored as a string:
+
+@lisp
+(string? (thing-name (thing (name "some-name"))))
+@result{} #t
+(string? (thing-name (thing (name 'some-name))))
+@result{} #t
+(thing (name 1994))
+@result{} Throw to key `bad!' with args `(1994)'.
+@end lisp
+
+@item (thunked)
+Fields marked as @code{thunked} will actually compute the field's value in the
+current dynamic extent which is useful when referring to fluids in a field's
+value. Furthermore, that thunk can access the record it belongs to via the
+@code{this-identifier}. For example:
+
+@lisp
+(define-record-type* <rectangle> rectangle make-rectangle
+  rectangle?
+  this-rectangle
+  (width  rectangle-width)
+  (height rectangle-height)
+  (area rectangle-area (thunked)
+                       (default (* (rectangle-width  this-rectangle)
+                                   (rectangle-height this-rectangle)))))
+
+(define base-rectangle
+  (rectangle
+    (width  2)
+    (height 4)))
+
+(define derived-rectangle
+  (rectangle
+    (inherit base)
+    (width   6)))
+
+(rectangle-area base-rectangle)
+@result{} 8
+
+(rectangle-area derived-rectangle
+@result{} 24
+@end lisp
+
+@item (delayed)
+Fields marked as @code{delayed} are similar to @code{thunked} fields, except
+that they are effectively wrapped in a @code{(delay @dots{})} form. Note that
+delayed fields cannot use @code{this-identifier}.
+@end table
+@end table
+@end defmac
+
 @node Invoking guix repl
 @section Invoking @command{guix repl}
 

base-commit: 2b782f67266b42bb40015bd23ce2443be2f9b01f
-- 
2.41.0





Message sent:


Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
MIME-Version: 1.0
X-Mailer: MIME-tools 5.505 (Entity 5.505)
Content-Type: text/plain; charset=utf-8
X-Loop: help-debbugs@HIDDEN
From: help-debbugs@HIDDEN (GNU bug Tracking System)
To: Skyler Ferris <skyvine@HIDDEN>
Subject: bug#67786: Acknowledgement ([PATCH] doc: Add documentation for
 define-record-type*)
Message-ID: <handler.67786.B.17023258314339.ack <at> debbugs.gnu.org>
References: <9bf2efa9c7aab1661fcf5180d1e536fc6dc0e9b3.1702324538.git.skyvine@HIDDEN>
X-Gnu-PR-Message: ack 67786
X-Gnu-PR-Package: guix-patches
X-Gnu-PR-Keywords: patch
Reply-To: 67786 <at> debbugs.gnu.org
Date: Mon, 11 Dec 2023 20:18:02 +0000

Thank you for filing a new bug report with debbugs.gnu.org.

This is an automatically generated reply to let you know your message
has been received.

Your message is being forwarded to the package maintainers and other
interested parties for their attention; they will reply in due course.

Your message has been sent to the package maintainer(s):
 guix-patches@HIDDEN

If you wish to submit further information on this problem, please
send it to 67786 <at> debbugs.gnu.org.

Please do not send mail to help-debbugs@HIDDEN unless you wish
to report a problem with the Bug-tracking system.

--=20
67786: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=3D67786
GNU Bug Tracking System
Contact help-debbugs@HIDDEN with problems


Message received at control <at> debbugs.gnu.org:


Received: (at control) by debbugs.gnu.org; 25 Dec 2023 17:38:42 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Mon Dec 25 12:38:42 2023
Received: from localhost ([127.0.0.1]:55284 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1rHouY-0005Qc-Gg
	for submit <at> debbugs.gnu.org; Mon, 25 Dec 2023 12:38:42 -0500
Received: from eggs.gnu.org ([2001:470:142:3::10]:60252)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <mathieu@HIDDEN>)
 id 1rHouW-0005QQ-TX
 for control <at> debbugs.gnu.org; Mon, 25 Dec 2023 12:38:41 -0500
Received: from fencepost.gnu.org ([2001:470:142:3::e])
 by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.90_1)
 (envelope-from <mathieu@HIDDEN>)
 id 1rHouJ-0002F2-Jx
 for control <at> debbugs.gnu.org; Mon, 25 Dec 2023 12:38:27 -0500
Date: Mon, 25 Dec 2023 18:38:25 +0100
Message-Id: <87frzqi3n2.fsf@HIDDEN>
To: control <at> debbugs.gnu.org
From: Mathieu Othacehe <mathieu@HIDDEN>
Subject: control message for bug #67787
X-Spam-Score: -1.9 (-)
X-Debbugs-Envelope-To: control
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -2.9 (--)

merge 67787 67786
quit





Message sent to guix-patches@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: [bug#67786] doc: Add documentation for define-record-type*
References: <9bf2efa9c7aab1661fcf5180d1e536fc6dc0e9b3.1702324538.git.skyvine@HIDDEN>
In-Reply-To: <9bf2efa9c7aab1661fcf5180d1e536fc6dc0e9b3.1702324538.git.skyvine@HIDDEN>
Resent-From: Skyler Ferris <skyvine@HIDDEN>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: guix-patches@HIDDEN
Resent-Date: Thu, 28 Dec 2023 00:31:02 +0000
Resent-Message-ID: <handler.67786.B67786.170372340615963 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: followup 67786
X-GNU-PR-Package: guix-patches
X-GNU-PR-Keywords: patch
To: 67786 <at> debbugs.gnu.org
Received: via spool by 67786-submit <at> debbugs.gnu.org id=B67786.170372340615963
          (code B ref 67786); Thu, 28 Dec 2023 00:31:02 +0000
Received: (at 67786) by debbugs.gnu.org; 28 Dec 2023 00:30:06 +0000
Received: from localhost ([127.0.0.1]:38097 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1rIeHk-00046l-9r
	for submit <at> debbugs.gnu.org; Wed, 27 Dec 2023 19:30:05 -0500
Received: from mail-40134.protonmail.ch ([185.70.40.134]:57475)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <skyvine@HIDDEN>) id 1rIeHf-00041i-PD
 for 67786 <at> debbugs.gnu.org; Wed, 27 Dec 2023 19:30:02 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com;
 s=protonmail3; t=1703723393; x=1703982593;
 bh=edeYyfdsS4v0Ic9L8nZdhj7i9ZGMg7t/ZNMhci1azgA=;
 h=Date:To:From:Subject:Message-ID:Feedback-ID:From:To:Cc:Date:
 Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector;
 b=U3dp0Mw0ZhHT4ooRb5i0NTSajEM63uE8YzQBZ8olAD/acsh8lrr22bujh2aqPLine
 3fhW7sh2rzNVNrkxy610GU8zHVqbZHblHRtQQSvVk+16QFUfDXg1/vq7eh7WH4oqrO
 TFP482xa/3ZsLfovXFxSByy6YW7TIbiQ7E5zTgfOe6ipPLp27iZwZgq8ZbytNs+kav
 HkmKVA1CaLAwp6xvPHrphw3Xuvkf7bEi1W9KbKF+2ek4gDa4GrG1DUr8JOoK2DtuPG
 Vd1RXAZii1Vflbhv1tnDJH9r5jxDk/yQoGbv8l7QFlNWS9AB6dLlo3lCRTMSgLmlTo
 YyZrLSIAN2+2A==
Date: Thu, 28 Dec 2023 00:29:43 +0000
From: Skyler Ferris <skyvine@HIDDEN>
Message-ID: <10d46484-1f83-4b5f-9cc7-3d9d68998b33@HIDDEN>
Feedback-ID: 40635331:user:proton
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
X-Spam-Score: -0.0 (/)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

I wrote this documentation by using the docstring in guix/record.scm as a
starting point and expanding on it/reformatting on it to be appropriate
for inclusion in a manual.

* doc/guix.texi: Add sections describing the typical
usage and API for define-record-type*

Change-Id: I19e7220553d10652c794e6e0172b2c9ee961f54f
---
# This version of the patch updates the commit message to explain that I
# wrote the documentation by using the docstring in guix/records.scm as
# a starting point. This process seemed appropriate to me because it is
# being incorporated into the same project for the same purpose. Most of
# the commit is new content, but some of it is shared with the docstring
# - for example the "thing" struct definition and the explanation of
# thunked. I think that it is useful for the manual and the
# docstrings to share content when appropriate to avoid accidentally
# communicating contradictory ideas to different audiences, but the
# relationship should still be acknowledged. If there is a more formal
# manner in which I should indicate this please let me know and I will
# be happy to update the commit. This version does not change anything
# other than the commit message.
 =C2=A0doc/contributing.texi |=C2=A0=C2=A0 1 -
 =C2=A0doc/guix.texi=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 | 274 =
++++++++++++++++++++++++++++++++++++++++++
 =C2=A02 files changed, 274 insertions(+), 1 deletion(-)

diff --git a/doc/contributing.texi b/doc/contributing.texi
index 7337f4bd58..d920b2589a 100644
--- a/doc/contributing.texi
+++ b/doc/contributing.texi
@@ -1313,7 +1313,6 @@ Data Types and Pattern Matching
 =C2=A0notably the fact that it is hard to read, error-prone, and a hindran=
ce
 =C2=A0to proper type error reports.

-@findex define-record-type*
 =C2=A0@findex match-record
 =C2=A0@cindex pattern matching
 =C2=A0Guix code should define appropriate data types (for instance, using
diff --git a/doc/guix.texi b/doc/guix.texi
index e61a893af9..3cb15eeca3 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -12606,6 +12606,280 @@ G-Expressions
 =C2=A0@code{(*approximate*)}, but this may change.
 =C2=A0@end deffn

+@node Records in Guix
+@section Records in Guix
+Guix uses @code{define-record-type*} to define structures with a lispy=20
format.
+Packages, operating systems, etc are all defined with
+@code{define-record-type*} facilities. If one was using this facility to
+define preferences for a text editor, it might look like this:
+
+@lisp
+;; The only valid emulation modes are the symbol 'emacs, the symbol=20
'vim, or
+;; the boolean #f. As a convenience to the user, if they pass in a string
+;; first convert it to a symbol and accept it if it is valid.
+(define (sanitize-emulation-mode value)
+=C2=A0 (let ((symbolized-value (cond ((not value)=C2=A0=C2=A0=C2=A0=C2=
=A0 #f)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ((string? value) (string->sym=
bol value))
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (#t=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 value))))
+=C2=A0=C2=A0=C2=A0 (unless (or (not symbolized-value)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 (eq? symbolized-value 'emacs)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 (eq? symbolized-value 'vim))
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (throw 'bad-emulation-made
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 (format #f "Unrecognized emulation mode: ~s" value)))
+=C2=A0=C2=A0=C2=A0 symbolized-value))
+
+(define-record-type*
+=C2=A0 <editor-preferences> editor-preferences make-editor-preferences
+=C2=A0 editor-preferences? this-editor-preferences
+=C2=A0 (background-color editor-preferences-background-color
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (default "000000"))
+=C2=A0 (text-color=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 editor-preferences-=
text-color
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (default "FFFFFF"))
+=C2=A0 (emulation-mode=C2=A0=C2=A0 editor-preferences-emulation-mode
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (default #f)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (sanitize sanitize-emulation-=
mode)))
+@end lisp
+
+A user could then define their preferences like this:
+
+@lisp
+(define my-preferences
+=C2=A0 (editor-preferences
+=C2=A0=C2=A0=C2=A0 (background-color "222222")
+=C2=A0=C2=A0=C2=A0 (emulation-mode=C2=A0=C2=A0 'vim)))
+@end lisp
+
+The value contained in @code{my-preferences} contains a custom
+@code{background-color} and @code{emulation-mode}, but keeps the default
+@code{text-color} (@code{"FFFFFF"}). If an invalid=20
@code{emulation-mode} had
+been specified, for example if the user passed in @code{"vi"} instead of
+@code{"vim"}, @code{sanitize-emulation-mode} would immediately throw an=20
error.
+
+The program can access values like this:
+
+@lisp
+(editor-preferences-background-color my-preferences)
+@result{} "222222"
+(editor-preferences-text-color my-preferences)
+@result{} "FFFFFF"
+(editor-preferences-emulation-mode my-preferences)
+@result{} 'vim
+@end lisp
+
+There is no way to define setters (all instances are immutable).
+
+@node Record Inheritance
+@subsection Record Inheritance
+It is also possible to inherit from previously defined instances when=20
creating
+new ones. Continuing with the editor example, someone might want to=20
base their
+preferences on their friend's preferences but customize a value:
+
+@lisp
+(define friends-preferences
+=C2=A0 (editor-preferences
+=C2=A0=C2=A0=C2=A0 (inherit my-preferences)
+=C2=A0=C2=A0=C2=A0 (emulation-mode 'emacs)))
+@end lisp
+
+This keeps the same @code{background-color} and @code{text-color} that are
+contained in @code{my-preferences} but changes the @code{emulation-mode} t=
o
+be @code{'emacs} instead of @code{'vim}.
+
+Sometimes it does not make sense for a field to be inherited. Suppose=20
that the
+@code{<editor-preferences>} type is updated to contain a username so that =
a
+friendly greeting can be displayed when the program starts up:
+
+@lisp
+;; Usernames must be strings. It would be strange to pass a username as a
+;; symbol, so throw an error in case the user meant to pass in a variable'=
s
+;; value instead of a literal symbol.
+(define (sanitize-username value)
+=C2=A0 (unless (string? value)
+=C2=A0=C2=A0=C2=A0 (throw 'bad-username
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (format #f "U=
sernames must be strings! Got: ~s" value)))
+=C2=A0 value)
+
+(define (sanitize-emulation-mode value)
+=C2=A0 (let ((symbolized-value (cond ((not value)=C2=A0=C2=A0=C2=A0=C2=
=A0 #f)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ((string? value) (string->sym=
bol value))
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (#t=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 value))))
+=C2=A0=C2=A0=C2=A0 (unless (or (not symbolized-value)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 (eq? symbolized-value 'emacs)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 (eq? symbolized-value 'vim))
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (throw 'bad-emulation-made
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 (format #f "Unrecognized emulation mode: ~s" value)))
+=C2=A0=C2=A0=C2=A0 symbolized-value))
+
+(define-record-type*
+=C2=A0 <editor-preferences> editor-preferences make-editor-preferences
+=C2=A0 editor-preferences? this-editor-preferences
+=C2=A0 (username=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 editor-pr=
eferences-username
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (innate)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (sanitize sanitize-username))
+=C2=A0 (background-color editor-preferences-background-color
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (default "000000"))
+=C2=A0 (text-color=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 editor-preferences-=
text-color
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (default "FFFFFF"))
+=C2=A0 (emulation-mode=C2=A0=C2=A0 editor-preferences-emulation-mode
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (default #f)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (sanitize sanitize-emulation-=
mode)))
+@end lisp
+
+There are a couple of differences in the new @code{username} field=20
compared to
+the fields we looked at earlier. It is marked as @code{innate}, which mean=
s
+that it will not be inherited. For example, consider what would happen=20
if we
+tried to define new instances like this:
+
+@lisp
+(define my-preferences
+=C2=A0 (editor-preferences
+=C2=A0=C2=A0=C2=A0 (username=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0 "my-username")
+=C2=A0=C2=A0=C2=A0 (background-color "222222")
+=C2=A0=C2=A0=C2=A0 (emulation-mode=C2=A0=C2=A0 'vim)))
+
+(define friends-preferences
+=C2=A0 (editor-preferences
+=C2=A0=C2=A0=C2=A0 (inherit my-preferences)
+=C2=A0=C2=A0=C2=A0 (emulation-mode 'emacs)))
+@end lisp
+
+While the @code{friends-preferences} instance still inherits the values fo=
r
+@code{background-color} and @code{text-color}, it will not inherit the=20
value
+for @code{username}. Furthermore, as the @code{username} field does not=20
define
+a default value the attempted creation of @code{friends-preferences} will
+actually throw an error. Instead, we could do this:
+
+@lisp
+(define my-preferences
+=C2=A0 (editor-preferences
+=C2=A0=C2=A0=C2=A0 (username=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0 "my-username")
+=C2=A0=C2=A0=C2=A0 (background-color "222222")
+=C2=A0=C2=A0=C2=A0 (emulation-mode=C2=A0=C2=A0 'vim)))
+
+(define friends-preferences
+=C2=A0 (editor-preferences
+=C2=A0=C2=A0=C2=A0 (inherit=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 my-p=
references)
+=C2=A0=C2=A0=C2=A0 (username=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 "friends-=
username")
+=C2=A0=C2=A0=C2=A0 (emulation-mode 'emacs)))
+@end lisp
+
+@node @code{define-record-type*} Reference
+@subsection @code{define-record-type*} Reference
+@defmac define-record-type* name syntactic-constructor constructor=20
predicate this-identifier fields ...
+
+Define a new record type and associated helpers.
+
+@table @var
+@item name
+A symbol used to name the type, as would normally be provided to a plain
+@code{define-record-type} form. For example, @code{<package>}.
+
+@item syntactic-constructor
+A symbol that will be used to define the user-facing constructor. For=20
example,
+the symbol @code{package} is the syntactic constructor for the=20
@code{<package>}
+structure.
+
+@item constructor
+A symbol that will be used to define the traditional constructor. It is=20
used in
+the implementation of the syntactic constructor, but will not typically=20
be used
+elsewhere. The traditional @code{make-name} (for example,=20
@code{make-package})
+is a fine value to use here.
+
+@item predicate
+A symbol that will be used to test if a value is an instance of this=20
record.
+For example, @code{package?}.
+
+@item this-identifier
+This symbol can be used when defining fields that need to refer to the=20
struct
+that contains them. For an example of this, see the @code{thunked} field
+property, below.
+
+@item fields
+A set of field specifiers which take the following form:
+
+@lisp
+(field-name field-getter properties ...)
+@end lisp
+
+Each of the properties must have one of the following forms:
+
+@table @code
+@item (default @var{value})
+Defines the default value for the field, if the user does not specify=20
one using
+the syntactic constructor.
+
+@item (innate)
+Fields marked as innate will not be inherited from parent objects (see
+Instantiating Records, below, for details of object inheritance).
+
+@item (sanitize @var{proc})
+The value given by the user will be passed into @var{proc} before being=20
stored
+in the object. For example, consider this struct definition:
+
+@lisp
+(define-record-type* <thing> thing make-thing
+=C2=A0 thing?
+=C2=A0 this-thing
+=C2=A0 (name=C2=A0 thing-name
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (sanitize (lambda (value)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (cond ((string? value) =
value)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 ((symbol? value) (symbol->string value))
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 (else (throw 'bad! value)))))))
+@end lisp
+
+When creating @code{thing} instances either a string or a symbol can be
+supplied but it will always be stored as a string:
+
+@lisp
+(string? (thing-name (thing (name "some-name"))))
+@result{} #t
+(string? (thing-name (thing (name 'some-name))))
+@result{} #t
+(thing (name 1994))
+@result{} Throw to key `bad!' with args `(1994)'.
+@end lisp
+
+@item (thunked)
+Fields marked as @code{thunked} will actually compute the field's value=20
in the
+current dynamic extent which is useful when referring to fluids in a=20
field's
+value. Furthermore, that thunk can access the record it belongs to via the
+@code{this-identifier}. For example:
+
+@lisp
+(define-record-type* <rectangle> rectangle make-rectangle
+=C2=A0 rectangle?
+=C2=A0 this-rectangle
+=C2=A0 (width=C2=A0 rectangle-width)
+=C2=A0 (height rectangle-height)
+=C2=A0 (area rectangle-area (thunked)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (default (*=
 (rectangle-width this-rectangle)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (rectangle-=
height this-rectangle)))))
+
+(define base-rectangle
+=C2=A0 (rectangle
+=C2=A0=C2=A0=C2=A0 (width=C2=A0 2)
+=C2=A0=C2=A0=C2=A0 (height 4)))
+
+(define derived-rectangle
+=C2=A0 (rectangle
+=C2=A0=C2=A0=C2=A0 (inherit base)
+=C2=A0=C2=A0=C2=A0 (width=C2=A0=C2=A0 6)))
+
+(rectangle-area base-rectangle)
+@result{} 8
+
+(rectangle-area derived-rectangle
+@result{} 24
+@end lisp
+
+@item (delayed)
+Fields marked as @code{delayed} are similar to @code{thunked} fields,=20
except
+that they are effectively wrapped in a @code{(delay @dots{})} form.=20
Note that
+delayed fields cannot use @code{this-identifier}.
+@end table
+@end table
+@end defmac
+
 =C2=A0@node Invoking guix repl
 =C2=A0@section Invoking @command{guix repl}

--=20
2.41.0






Message sent to guix-patches@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: [bug#67786] doc: Add documentation for define-record-type*
Resent-From: Skyler Ferris <skyvine@HIDDEN>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: guix-patches@HIDDEN
Resent-Date: Thu, 28 Dec 2023 01:24:02 +0000
Resent-Message-ID: <handler.67786.B67786.170372663528503 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: followup 67786
X-GNU-PR-Package: guix-patches
X-GNU-PR-Keywords: patch
To: 67786 <at> debbugs.gnu.org
Received: via spool by 67786-submit <at> debbugs.gnu.org id=B67786.170372663528503
          (code B ref 67786); Thu, 28 Dec 2023 01:24:02 +0000
Received: (at 67786) by debbugs.gnu.org; 28 Dec 2023 01:23:55 +0000
Received: from localhost ([127.0.0.1]:38132 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1rIf7q-0007Pe-C5
	for submit <at> debbugs.gnu.org; Wed, 27 Dec 2023 20:23:55 -0500
Received: from mail-40133.protonmail.ch ([185.70.40.133]:13889)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <skyvine@HIDDEN>) id 1rIf7n-0007PG-7C
 for 67786 <at> debbugs.gnu.org; Wed, 27 Dec 2023 20:23:52 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com;
 s=protonmail3; t=1703726625; x=1703985825;
 bh=UMEEOINjtXbTms6xqpUqQ7rALvdBrrkjk6VuxipvhcA=;
 h=Date:To:From:Subject:Message-ID:In-Reply-To:References:
 Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID:
 Message-ID:BIMI-Selector;
 b=ruGcYyY1nDJhjQwOxEiUBlhfOsiwOhkXMVJjYH24KvW8T92nI+TylNR1RDwtuZzUq
 KM9mfLKcrcrSecCHIFiEaJVT9QpcTB0OVmnI7WGlt7kCFBD+/7tXVS70WwM7Vg/1SL
 HpyiMt7HYszogMaTEBsSts8DCUiZdIfGoIlaxUG9vdAks1ay0gadkuvHfJ/PQsAWU2
 /1GCqaNbBeI0jP6o5sUxkyLCyn/DoouLYamZvo53GvD8PYIPaGQ8TxIeVvFPXbvWll
 rvI4N6z/W+jEtkGtwOKyTPQ5sO8XnND+x3UaddoLY6p9KxTgQ9vrkRxqF/f31C37+v
 2XEZdzY4flqiA==
Date: Thu, 28 Dec 2023 01:23:21 +0000
From: Skyler Ferris <skyvine@HIDDEN>
Message-ID: <58aa08f2-37c2-47ab-a16d-99d13e24e911@HIDDEN>
In-Reply-To: <10d46484-1f83-4b5f-9cc7-3d9d68998b33@HIDDEN>
References: <10d46484-1f83-4b5f-9cc7-3d9d68998b33@HIDDEN>
Feedback-ID: 40635331:user:proton
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
X-Spam-Score: -0.0 (/)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

I wrote this documentation by using the docstring in guix/record.scm as a
starting point and expanding on it/reformatting on it to be appropriate
for inclusion in a manual.

* doc/guix.texi: Add sections describing the typical
usage and API for define-record-type*

Change-Id: I19e7220553d10652c794e6e0172b2c9ee961f54f
---
# It looks like when I sent the last message the spaces in the diff got
# converted to non-breaking spaces, which makes it difficult to read in
# some clients. This version should be easier to read. The notes from
# the previous message are preserved below:
#
# This version of the patch updates the commit message to explain that I
# wrote the documentation by using the docstring in guix/records.scm as
# a starting point. This process seemed appropriate to me because it is
# being incorporated into the same project for the same purpose. Most of
# the commit is new content, but some of it is shared with the docstring
# - for example the "thing" struct definition and the explanation of
# struct fields. I think that it is useful for the manual and the
# docstrings to share content when appropriate to avoid accidentally
# communicating contradictory ideas to different audiences, but the
# relationship should still be acknowledged. If there is a more formal
# manner in which I should indicate this please let me know and I will
# be happy to update the commit. This version does not change anything
# other than the commit message.
 =C2=A0doc/contributing.texi |=C2=A0=C2=A0 1 -
 =C2=A0doc/guix.texi=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 | 274 =
++++++++++++++++++++++++++++++++++++++++++
 =C2=A02 files changed, 274 insertions(+), 1 deletion(-)

diff --git a/doc/contributing.texi b/doc/contributing.texi
index 7337f4bd58..d920b2589a 100644
--- a/doc/contributing.texi
+++ b/doc/contributing.texi
@@ -1313,7 +1313,6 @@ Data Types and Pattern Matching
 =C2=A0notably the fact that it is hard to read, error-prone, and a hindran=
ce
 =C2=A0to proper type error reports.

-@findex define-record-type*
 =C2=A0@findex match-record
 =C2=A0@cindex pattern matching
 =C2=A0Guix code should define appropriate data types (for instance, using
diff --git a/doc/guix.texi b/doc/guix.texi
index e61a893af9..3cb15eeca3 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -12606,6 +12606,280 @@ G-Expressions
 =C2=A0@code{(*approximate*)}, but this may change.
 =C2=A0@end deffn

+@node Records in Guix
+@section Records in Guix
+Guix uses @code{define-record-type*} to define structures with a lispy=20
format.
+Packages, operating systems, etc are all defined with
+@code{define-record-type*} facilities. If one was using this facility to
+define preferences for a text editor, it might look like this:
+
+@lisp
+;; The only valid emulation modes are the symbol 'emacs, the symbol=20
'vim, or
+;; the boolean #f. As a convenience to the user, if they pass in a string
+;; first convert it to a symbol and accept it if it is valid.
+(define (sanitize-emulation-mode value)
+=C2=A0 (let ((symbolized-value (cond ((not value)=C2=A0=C2=A0=C2=A0=C2=
=A0 #f)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ((string? value) (string->sym=
bol value))
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (#t=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 value))))
+=C2=A0=C2=A0=C2=A0 (unless (or (not symbolized-value)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 (eq? symbolized-value 'emacs)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 (eq? symbolized-value 'vim))
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (throw 'bad-emulation-made
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 (format #f "Unrecognized emulation mode: ~s" value)))
+=C2=A0=C2=A0=C2=A0 symbolized-value))
+
+(define-record-type*
+=C2=A0 <editor-preferences> editor-preferences make-editor-preferences
+=C2=A0 editor-preferences? this-editor-preferences
+=C2=A0 (background-color editor-preferences-background-color
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (default "000000"))
+=C2=A0 (text-color=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 editor-preferences-=
text-color
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (default "FFFFFF"))
+=C2=A0 (emulation-mode=C2=A0=C2=A0 editor-preferences-emulation-mode
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (default #f)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (sanitize sanitize-emulation-=
mode)))
+@end lisp
+
+A user could then define their preferences like this:
+
+@lisp
+(define my-preferences
+=C2=A0 (editor-preferences
+=C2=A0=C2=A0=C2=A0 (background-color "222222")
+=C2=A0=C2=A0=C2=A0 (emulation-mode=C2=A0=C2=A0 'vim)))
+@end lisp
+
+The value contained in @code{my-preferences} contains a custom
+@code{background-color} and @code{emulation-mode}, but keeps the default
+@code{text-color} (@code{"FFFFFF"}). If an invalid=20
@code{emulation-mode} had
+been specified, for example if the user passed in @code{"vi"} instead of
+@code{"vim"}, @code{sanitize-emulation-mode} would immediately throw an=20
error.
+
+The program can access values like this:
+
+@lisp
+(editor-preferences-background-color my-preferences)
+@result{} "222222"
+(editor-preferences-text-color my-preferences)
+@result{} "FFFFFF"
+(editor-preferences-emulation-mode my-preferences)
+@result{} 'vim
+@end lisp
+
+There is no way to define setters (all instances are immutable).
+
+@node Record Inheritance
+@subsection Record Inheritance
+It is also possible to inherit from previously defined instances when=20
creating
+new ones. Continuing with the editor example, someone might want to=20
base their
+preferences on their friend's preferences but customize a value:
+
+@lisp
+(define friends-preferences
+=C2=A0 (editor-preferences
+=C2=A0=C2=A0=C2=A0 (inherit my-preferences)
+=C2=A0=C2=A0=C2=A0 (emulation-mode 'emacs)))
+@end lisp
+
+This keeps the same @code{background-color} and @code{text-color} that are
+contained in @code{my-preferences} but changes the @code{emulation-mode} t=
o
+be @code{'emacs} instead of @code{'vim}.
+
+Sometimes it does not make sense for a field to be inherited. Suppose=20
that the
+@code{<editor-preferences>} type is updated to contain a username so that =
a
+friendly greeting can be displayed when the program starts up:
+
+@lisp
+;; Usernames must be strings. It would be strange to pass a username as a
+;; symbol, so throw an error in case the user meant to pass in a variable'=
s
+;; value instead of a literal symbol.
+(define (sanitize-username value)
+=C2=A0 (unless (string? value)
+=C2=A0=C2=A0=C2=A0 (throw 'bad-username
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (format #f "U=
sernames must be strings! Got: ~s" value)))
+=C2=A0 value)
+
+(define (sanitize-emulation-mode value)
+=C2=A0 (let ((symbolized-value (cond ((not value)=C2=A0=C2=A0=C2=A0=C2=
=A0 #f)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ((string? value) (string->sym=
bol value))
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (#t=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 value))))
+=C2=A0=C2=A0=C2=A0 (unless (or (not symbolized-value)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 (eq? symbolized-value 'emacs)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 (eq? symbolized-value 'vim))
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (throw 'bad-emulation-made
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 (format #f "Unrecognized emulation mode: ~s" value)))
+=C2=A0=C2=A0=C2=A0 symbolized-value))
+
+(define-record-type*
+=C2=A0 <editor-preferences> editor-preferences make-editor-preferences
+=C2=A0 editor-preferences? this-editor-preferences
+=C2=A0 (username=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 editor-pr=
eferences-username
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (innate)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (sanitize sanitize-username))
+=C2=A0 (background-color editor-preferences-background-color
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (default "000000"))
+=C2=A0 (text-color=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 editor-preferences-=
text-color
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (default "FFFFFF"))
+=C2=A0 (emulation-mode=C2=A0=C2=A0 editor-preferences-emulation-mode
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (default #f)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (sanitize sanitize-emulation-=
mode)))
+@end lisp
+
+There are a couple of differences in the new @code{username} field=20
compared to
+the fields we looked at earlier. It is marked as @code{innate}, which mean=
s
+that it will not be inherited. For example, consider what would happen=20
if we
+tried to define new instances like this:
+
+@lisp
+(define my-preferences
+=C2=A0 (editor-preferences
+=C2=A0=C2=A0=C2=A0 (username=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0 "my-username")
+=C2=A0=C2=A0=C2=A0 (background-color "222222")
+=C2=A0=C2=A0=C2=A0 (emulation-mode=C2=A0=C2=A0 'vim)))
+
+(define friends-preferences
+=C2=A0 (editor-preferences
+=C2=A0=C2=A0=C2=A0 (inherit my-preferences)
+=C2=A0=C2=A0=C2=A0 (emulation-mode 'emacs)))
+@end lisp
+
+While the @code{friends-preferences} instance still inherits the values fo=
r
+@code{background-color} and @code{text-color}, it will not inherit the=20
value
+for @code{username}. Furthermore, as the @code{username} field does not=20
define
+a default value the attempted creation of @code{friends-preferences} will
+actually throw an error. Instead, we could do this:
+
+@lisp
+(define my-preferences
+=C2=A0 (editor-preferences
+=C2=A0=C2=A0=C2=A0 (username=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0 "my-username")
+=C2=A0=C2=A0=C2=A0 (background-color "222222")
+=C2=A0=C2=A0=C2=A0 (emulation-mode=C2=A0=C2=A0 'vim)))
+
+(define friends-preferences
+=C2=A0 (editor-preferences
+=C2=A0=C2=A0=C2=A0 (inherit=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 my-p=
references)
+=C2=A0=C2=A0=C2=A0 (username=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 "friends-=
username")
+=C2=A0=C2=A0=C2=A0 (emulation-mode 'emacs)))
+@end lisp
+
+@node @code{define-record-type*} Reference
+@subsection @code{define-record-type*} Reference
+@defmac define-record-type* name syntactic-constructor constructor=20
predicate this-identifier fields ...
+
+Define a new record type and associated helpers.
+
+@table @var
+@item name
+A symbol used to name the type, as would normally be provided to a plain
+@code{define-record-type} form. For example, @code{<package>}.
+
+@item syntactic-constructor
+A symbol that will be used to define the user-facing constructor. For=20
example,
+the symbol @code{package} is the syntactic constructor for the=20
@code{<package>}
+structure.
+
+@item constructor
+A symbol that will be used to define the traditional constructor. It is=20
used in
+the implementation of the syntactic constructor, but will not typically=20
be used
+elsewhere. The traditional @code{make-name} (for example,=20
@code{make-package})
+is a fine value to use here.
+
+@item predicate
+A symbol that will be used to test if a value is an instance of this=20
record.
+For example, @code{package?}.
+
+@item this-identifier
+This symbol can be used when defining fields that need to refer to the=20
struct
+that contains them. For an example of this, see the @code{thunked} field
+property, below.
+
+@item fields
+A set of field specifiers which take the following form:
+
+@lisp
+(field-name field-getter properties ...)
+@end lisp
+
+Each of the properties must have one of the following forms:
+
+@table @code
+@item (default @var{value})
+Defines the default value for the field, if the user does not specify=20
one using
+the syntactic constructor.
+
+@item (innate)
+Fields marked as innate will not be inherited from parent objects (see
+Instantiating Records, below, for details of object inheritance).
+
+@item (sanitize @var{proc})
+The value given by the user will be passed into @var{proc} before being=20
stored
+in the object. For example, consider this struct definition:
+
+@lisp
+(define-record-type* <thing> thing make-thing
+=C2=A0 thing?
+=C2=A0 this-thing
+=C2=A0 (name=C2=A0 thing-name
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (sanitize (lambda (value)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (cond ((string? value) =
value)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 ((symbol? value) (symbol->string value))
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 (else (throw 'bad! value)))))))
+@end lisp
+
+When creating @code{thing} instances either a string or a symbol can be
+supplied but it will always be stored as a string:
+
+@lisp
+(string? (thing-name (thing (name "some-name"))))
+@result{} #t
+(string? (thing-name (thing (name 'some-name))))
+@result{} #t
+(thing (name 1994))
+@result{} Throw to key `bad!' with args `(1994)'.
+@end lisp
+
+@item (thunked)
+Fields marked as @code{thunked} will actually compute the field's value=20
in the
+current dynamic extent which is useful when referring to fluids in a=20
field's
+value. Furthermore, that thunk can access the record it belongs to via the
+@code{this-identifier}. For example:
+
+@lisp
+(define-record-type* <rectangle> rectangle make-rectangle
+=C2=A0 rectangle?
+=C2=A0 this-rectangle
+=C2=A0 (width=C2=A0 rectangle-width)
+=C2=A0 (height rectangle-height)
+=C2=A0 (area rectangle-area (thunked)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (default (*=
 (rectangle-width this-rectangle)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (rectangle-=
height this-rectangle)))))
+
+(define base-rectangle
+=C2=A0 (rectangle
+=C2=A0=C2=A0=C2=A0 (width=C2=A0 2)
+=C2=A0=C2=A0=C2=A0 (height 4)))
+
+(define derived-rectangle
+=C2=A0 (rectangle
+=C2=A0=C2=A0=C2=A0 (inherit base)
+=C2=A0=C2=A0=C2=A0 (width=C2=A0=C2=A0 6)))
+
+(rectangle-area base-rectangle)
+@result{} 8
+
+(rectangle-area derived-rectangle
+@result{} 24
+@end lisp
+
+@item (delayed)
+Fields marked as @code{delayed} are similar to @code{thunked} fields,=20
except
+that they are effectively wrapped in a @code{(delay @dots{})} form.=20
Note that
+delayed fields cannot use @code{this-identifier}.
+@end table
+@end table
+@end defmac
+
 =C2=A0@node Invoking guix repl
 =C2=A0@section Invoking @command{guix repl}

--=20
2.41.0





Message sent to guix-patches@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: [bug#67786] doc: Add documentation for define-record-type*
References: <9bf2efa9c7aab1661fcf5180d1e536fc6dc0e9b3.1702324538.git.skyvine@HIDDEN>
In-Reply-To: <9bf2efa9c7aab1661fcf5180d1e536fc6dc0e9b3.1702324538.git.skyvine@HIDDEN>
Resent-From: Skyler Ferris <skyvine@HIDDEN>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: guix-patches@HIDDEN
Resent-Date: Thu, 28 Dec 2023 02:05:02 +0000
Resent-Message-ID: <handler.67786.B67786.170372906230277 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: followup 67786
X-GNU-PR-Package: guix-patches
X-GNU-PR-Keywords: patch
To: 67786 <at> debbugs.gnu.org
Received: via spool by 67786-submit <at> debbugs.gnu.org id=B67786.170372906230277
          (code B ref 67786); Thu, 28 Dec 2023 02:05:02 +0000
Received: (at 67786) by debbugs.gnu.org; 28 Dec 2023 02:04:22 +0000
Received: from localhost ([127.0.0.1]:38176 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1rIfkz-0007sH-Vi
	for submit <at> debbugs.gnu.org; Wed, 27 Dec 2023 21:04:22 -0500
Received: from mail-40131.protonmail.ch ([185.70.40.131]:39493)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <skyvine@HIDDEN>) id 1rIfkx-0007rz-Gx
 for 67786 <at> debbugs.gnu.org; Wed, 27 Dec 2023 21:04:20 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com;
 s=protonmail3; t=1703729053; x=1703988253;
 bh=zXIv2tsz15omCYCjK5NdeyG18/+FZhrMiL6MvmYJbeU=;
 h=Date:To:From:Subject:Message-ID:Feedback-ID:From:To:Cc:Date:
 Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector;
 b=rIDlE/2n0FDMaSz1QZk9K3WSHcKwttFAyTKrur1zRlon+c8XFmADqivwYAEiT2FlQ
 M+mL2ri8YkWtycyWLtxuxssZDKN4vSpRAo0OXpZuGZUkSci9glUZJbNDJL0S017uR5
 Mf2xLcGlY4QEsQyxBZPrXbu4sq0xYhubNb+PnKH8EZwme8QSUKO9OToGHklGe3s/05
 +EyVCqNLWl2iWzOAovOpPaSzJtLK/V0kO0YppnDdeCk0dTrUkqZ9kVEgkuFrna5WuA
 l2qRl2Hs/9JQMadxZhhdxxia00AT+CXg0wBmFC6PXR3/NfHFvXY8QqrO2e5rGnR/2W
 kqOgyEamy5bVw==
Date: Thu, 28 Dec 2023 02:03:56 +0000
From: Skyler Ferris <skyvine@HIDDEN>
Message-ID: <b843a199-ad7c-43e4-8fe3-4f7bd77989b3@HIDDEN>
Feedback-ID: 40635331:user:proton
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
X-Spam-Score: -0.0 (/)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

It looks like the non-breaking space issue is still not resolved, and=20
I'm not immediately seeing how to fix it. I'll look at it more later. My=20
`git send-email` usage has been failing to deliver even though it worked=20
for previous patches, so I tried pasting the email into Thuderbird to=20
send it manually, but it seems like Thunderbird is stubborn about about=20
modifying the contents of my email automatically. It will probably work=20
best to fix the problem with `git send-email`.






Message sent to guix-patches@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: [bug#67786] doc: Add documentation for define-record-type*
Resent-From: Skyler Ferris <skyvine@HIDDEN>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: guix-patches@HIDDEN
Resent-Date: Fri, 29 Dec 2023 00:13:01 +0000
Resent-Message-ID: <handler.67786.B67786.170380874413338 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: followup 67786
X-GNU-PR-Package: guix-patches
X-GNU-PR-Keywords: patch
To: 67786 <at> debbugs.gnu.org
Received: via spool by 67786-submit <at> debbugs.gnu.org id=B67786.170380874413338
          (code B ref 67786); Fri, 29 Dec 2023 00:13:01 +0000
Received: (at 67786) by debbugs.gnu.org; 29 Dec 2023 00:12:24 +0000
Received: from localhost ([127.0.0.1]:40494 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1rJ0UC-0003T4-4C
	for submit <at> debbugs.gnu.org; Thu, 28 Dec 2023 19:12:24 -0500
Received: from mail-40131.protonmail.ch ([185.70.40.131]:55103)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <skyvine@HIDDEN>) id 1rJ0U7-0003Sm-IO
 for 67786 <at> debbugs.gnu.org; Thu, 28 Dec 2023 19:12:22 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com;
 s=protonmail3; t=1703808733; x=1704067933;
 bh=6ZAsDqXPflAVhkJa40M2TPpI9KZO3nEi9jlLGo1/RIA=;
 h=Date:To:From:Subject:Message-ID:In-Reply-To:References:
 Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID:
 Message-ID:BIMI-Selector;
 b=NN3LmXXX5BCiJvGCw83X1ZFk9dT2Il7u4w6wHhiwFtmEPDvZIJv13pqp6ebIxvhG9
 J5azjNS19z3mx9ZqC8AVKhV5jdoTWZiOhVltgYlQr5V9a094Bcgl7dS3+qjLXBosLs
 rezLeZU3j+pZTZcLZEcbV4+H8KGSBzUvHDW60Z/arTMSlNPO589qXnyNjd9cq4LlIh
 ke0R6hy0tgSWTjBnaL3ilQGIYc6KE4Tp0ToyXfg+SI+5WZr2yZ1KJ4EoG4sZBOR9Dl
 TYL3Pl7fflNqCqMpl9PEa1ElOTyGTtsg84ga4rYOFMx0KyHCftfGdUz03PFvQxIXap
 y3cyl6tUWs1UQ==
Date: Fri, 29 Dec 2023 00:12:01 +0000
From: Skyler Ferris <skyvine@HIDDEN>
Message-ID: <afc9e985-f66b-426e-b344-bfc3c9544622@HIDDEN>
In-Reply-To: <b843a199-ad7c-43e4-8fe3-4f7bd77989b3@HIDDEN>
References: <b843a199-ad7c-43e4-8fe3-4f7bd77989b3@HIDDEN>
Feedback-ID: 40635331:user:proton
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
X-Spam-Score: -0.0 (/)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

Hello again,

I'm not sure if the problem is on my end. I reviewed the logs for the=20
initial message I sent on December 11 and for the one I tried to send=20
yesterday. In both cases, exim indicates that it connected to the=20
appropriate endpoint, wrote a chunked message (BDAT), concluded with a=20
line like "SMTP<< 250 2.0.0 Ok: <number> bytes queued as <id>", then=20
closed the connection. The only difference is that when sending to=20
guix-patches@HIDDEN exim ended up talking to eggs.gnu.org, but when=20
sending to this bug's email address it talked to debbugs.gnu.org. Is=20
there someone I can talk to in order to help diagnose this issue?

Thanks,
Skyler





Message sent to guix-patches@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: [bug#67786] doc: Add documentation for define-record-type*
Resent-From: Skyler Ferris <skyvine@HIDDEN>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: guix-patches@HIDDEN
Resent-Date: Fri, 29 Dec 2023 00:18:01 +0000
Resent-Message-ID: <handler.67786.B67786.170380907023816 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: followup 67786
X-GNU-PR-Package: guix-patches
X-GNU-PR-Keywords: patch
To: 67786 <at> debbugs.gnu.org
Received: via spool by 67786-submit <at> debbugs.gnu.org id=B67786.170380907023816
          (code B ref 67786); Fri, 29 Dec 2023 00:18:01 +0000
Received: (at 67786) by debbugs.gnu.org; 29 Dec 2023 00:17:50 +0000
Received: from localhost ([127.0.0.1]:40499 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1rJ0ZR-0006C3-R1
	for submit <at> debbugs.gnu.org; Thu, 28 Dec 2023 19:17:50 -0500
Received: from mail-4316.protonmail.ch ([185.70.43.16]:62397)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <skyvine@HIDDEN>) id 1rJ0ZO-0006Bo-PS
 for 67786 <at> debbugs.gnu.org; Thu, 28 Dec 2023 19:17:49 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com;
 s=protonmail3; t=1703809060; x=1704068260;
 bh=5L3erPL51L8GhJ2+DKzldi1sPgAeIWZjEyJ6JzxMoUU=;
 h=Date:To:From:Subject:Message-ID:In-Reply-To:References:
 Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID:
 Message-ID:BIMI-Selector;
 b=BGqIl44kp0hRoxT8fiHreRRTEcPIizqoLl2WdBbA8vnBFqw+L3nuYyydyK2okd5Bh
 e73zT2RUoWRapU8liQa9D2X/8+qf0e9AlI6PMKJ06uKRCbLNqWIOonGCLLvow2in89
 5wSirwzZQr+sz8i25DzGtVfa8EFYr/KVprCwAY3cSEt5sdf84mOzzrQ5PcK8lXMJCk
 CvsrrSUF4N6SK2GM7KedRWOenfAQmY7VOXJgjuVBtAiyFIVkQ2OfxWZ1nRrL6cHxhV
 GPMUOwmbBvNwurPnvhfMvGO55PbUUtk2LX+jq3N+wCEpaMShEwp5KAAGXKvgySpQQl
 CIMU8qhkSBZZA==
Date: Fri, 29 Dec 2023 00:17:30 +0000
From: Skyler Ferris <skyvine@HIDDEN>
Message-ID: <39e76324-0f6a-4c3f-8dbf-c3e004c595f8@HIDDEN>
In-Reply-To: <b843a199-ad7c-43e4-8fe3-4f7bd77989b3@HIDDEN>
References: <b843a199-ad7c-43e4-8fe3-4f7bd77989b3@HIDDEN>
Feedback-ID: 40635331:user:proton
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
X-Spam-Score: -0.0 (/)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

Oh, I see that there is a help-debbugs mailing list. I'll reach out there.





Message sent to guix-patches@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: [bug#67786] doc: Add documentation for define-record-type*
References: <9bf2efa9c7aab1661fcf5180d1e536fc6dc0e9b3.1702324538.git.skyvine@HIDDEN>
In-Reply-To: <9bf2efa9c7aab1661fcf5180d1e536fc6dc0e9b3.1702324538.git.skyvine@HIDDEN>
Resent-From: skyvine@HIDDEN
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: guix-patches@HIDDEN
Resent-Date: Sat, 13 Jan 2024 18:53:02 +0000
Resent-Message-ID: <handler.67786.B67786.170517197522903 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: followup 67786
X-GNU-PR-Package: guix-patches
X-GNU-PR-Keywords: patch
To: 67786 <at> debbugs.gnu.org
Cc: Skyler Ferris <skyvine@HIDDEN>
Received: via spool by 67786-submit <at> debbugs.gnu.org id=B67786.170517197522903
          (code B ref 67786); Sat, 13 Jan 2024 18:53:02 +0000
Received: (at 67786) by debbugs.gnu.org; 13 Jan 2024 18:52:55 +0000
Received: from localhost ([127.0.0.1]:41080 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1rOj7m-0005xI-KK
	for submit <at> debbugs.gnu.org; Sat, 13 Jan 2024 13:52:55 -0500
Received: from mail-4316.protonmail.ch ([185.70.43.16]:54633)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <skyvine@HIDDEN>) id 1rOj7j-0005x1-TS
 for 67786 <at> debbugs.gnu.org; Sat, 13 Jan 2024 13:52:53 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com;
 s=protonmail3; t=1705171966; x=1705431166;
 bh=Dm4OsjoBQF0pB43gNCoKEC/2EYDpAKE8Nl+oxqxhPrQ=;
 h=Date:To:From:Cc:Subject:Message-ID:Feedback-ID:From:To:Cc:Date:
 Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector;
 b=W9klPWwsucf6ZxQOBp85m6BzQ/keJEUvz3Xme/W1WKDc1AcTWMxAQlDzST91pDfJe
 vplM2cR+jGfmmUNkknLK29GvjTNnffa3/fwpAt0vFtauS2k3sfyr+e+MDEYRmSCWhH
 tAMbDlahY4g4wUOG3XPD8a6IFwCRO4TJQuA8R/HtV8EteuznHJpFIX4AbZcvgpcmKV
 fV99xeVhcsd7pT/4TbVv2nRnAlOe/rlab+4sCWjZztQdLSr8mWsfdZ734sLEHceH6d
 hYWBGY6lPs6iU/Uph+HXywm9t/BdZT/HmfyU/UJ8aCJcvrxG6vL+InScEbOVbLor1y
 t5wcEYEMdthJQ==
Date: Sat, 13 Jan 2024 18:52:42 +0000
From: skyvine@HIDDEN
Message-ID: <43d0fdc9635394538ffee724beebe885d357bc59.1703713111.git.skyvine@HIDDEN>
Feedback-ID: 40635331:user:proton
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
X-Spam-Score: -0.0 (/)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

From: Skyler Ferris <skyvine@HIDDEN>

I wrote this documentation by using the docstring in guix/record.scm as a
starting point and expanding on it/reformatting on it to be appropriate
for inclusion in a manual.

* doc/guix.texi: Add sections describing the typical
usage and API for define-record-type*

Change-Id: I19e7220553d10652c794e6e0172b2c9ee961f54f
---
# This version of the patch updates the commit message to explain that I
# wrote the documentation by using the docstring in guix/records.scm as
# a starting point. This process seemed appropriate to me because it is
# being incorporated into the same project for the same purpose. Most of
# the commit is new content, but some of it is shared with the docstring
# - for example the "thing" struct definition and the explanation of
# struct fields. I think that it is useful for the manual and the
# docstrings to share content when appropriate to avoid accidentally
# communicating contradictory ideas to different audiences, but the
# relationship should still be acknowledged. If there is a more formal
# manner in which I should indicate this please let me know and I will
# be happy to update the commit. This version does not change anything
# other than the commit message.
 doc/contributing.texi |   1 -
 doc/guix.texi         | 274 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 274 insertions(+), 1 deletion(-)

diff --git a/doc/contributing.texi b/doc/contributing.texi
index 7337f4bd58..d920b2589a 100644
--- a/doc/contributing.texi
+++ b/doc/contributing.texi
@@ -1313,7 +1313,6 @@ Data Types and Pattern Matching
 notably the fact that it is hard to read, error-prone, and a hindrance
 to proper type error reports.
=20
-@findex define-record-type*
 @findex match-record
 @cindex pattern matching
 Guix code should define appropriate data types (for instance, using
diff --git a/doc/guix.texi b/doc/guix.texi
index e61a893af9..3cb15eeca3 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -12606,6 +12606,280 @@ G-Expressions
 @code{(*approximate*)}, but this may change.
 @end deffn
=20
+@node Records in Guix
+@section Records in Guix
+Guix uses @code{define-record-type*} to define structures with a lispy for=
mat.
+Packages, operating systems, etc are all defined with
+@code{define-record-type*} facilities. If one was using this facility to
+define preferences for a text editor, it might look like this:
+
+@lisp
+;; The only valid emulation modes are the symbol 'emacs, the symbol 'vim, =
or
+;; the boolean #f. As a convenience to the user, if they pass in a string
+;; first convert it to a symbol and accept it if it is valid.
+(define (sanitize-emulation-mode value)
+  (let ((symbolized-value (cond ((not value)     #f)
+                                ((string? value) (string->symbol value))
+                                (#t              value))))
+    (unless (or (not symbolized-value)
+                (eq? symbolized-value 'emacs)
+                (eq? symbolized-value 'vim))
+      (throw 'bad-emulation-made
+             (format #f "Unrecognized emulation mode: ~s" value)))
+    symbolized-value))
+
+(define-record-type*
+  <editor-preferences> editor-preferences make-editor-preferences
+  editor-preferences? this-editor-preferences
+  (background-color editor-preferences-background-color
+                    (default "000000"))
+  (text-color       editor-preferences-text-color
+                    (default "FFFFFF"))
+  (emulation-mode   editor-preferences-emulation-mode
+                    (default #f)
+                    (sanitize sanitize-emulation-mode)))
+@end lisp
+
+A user could then define their preferences like this:
+
+@lisp
+(define my-preferences
+  (editor-preferences
+    (background-color "222222")
+    (emulation-mode   'vim)))
+@end lisp
+
+The value contained in @code{my-preferences} contains a custom
+@code{background-color} and @code{emulation-mode}, but keeps the default
+@code{text-color} (@code{"FFFFFF"}). If an invalid @code{emulation-mode} h=
ad
+been specified, for example if the user passed in @code{"vi"} instead of
+@code{"vim"}, @code{sanitize-emulation-mode} would immediately throw an er=
ror.
+
+The program can access values like this:
+
+@lisp
+(editor-preferences-background-color my-preferences)
+@result{} "222222"
+(editor-preferences-text-color my-preferences)
+@result{} "FFFFFF"
+(editor-preferences-emulation-mode my-preferences)
+@result{} 'vim
+@end lisp
+
+There is no way to define setters (all instances are immutable).
+
+@node Record Inheritance
+@subsection Record Inheritance
+It is also possible to inherit from previously defined instances when crea=
ting
+new ones. Continuing with the editor example, someone might want to base t=
heir
+preferences on their friend's preferences but customize a value:
+
+@lisp
+(define friends-preferences
+  (editor-preferences
+    (inherit my-preferences)
+    (emulation-mode 'emacs)))
+@end lisp
+
+This keeps the same @code{background-color} and @code{text-color} that are
+contained in @code{my-preferences} but changes the @code{emulation-mode} t=
o
+be @code{'emacs} instead of @code{'vim}.
+
+Sometimes it does not make sense for a field to be inherited. Suppose that=
 the
+@code{<editor-preferences>} type is updated to contain a username so that =
a
+friendly greeting can be displayed when the program starts up:
+
+@lisp
+;; Usernames must be strings. It would be strange to pass a username as a
+;; symbol, so throw an error in case the user meant to pass in a variable'=
s
+;; value instead of a literal symbol.
+(define (sanitize-username value)
+  (unless (string? value)
+    (throw 'bad-username
+           (format #f "Usernames must be strings! Got: ~s" value)))
+  value)
+
+(define (sanitize-emulation-mode value)
+  (let ((symbolized-value (cond ((not value)     #f)
+                                ((string? value) (string->symbol value))
+                                (#t              value))))
+    (unless (or (not symbolized-value)
+                (eq? symbolized-value 'emacs)
+                (eq? symbolized-value 'vim))
+      (throw 'bad-emulation-made
+             (format #f "Unrecognized emulation mode: ~s" value)))
+    symbolized-value))
+
+(define-record-type*
+  <editor-preferences> editor-preferences make-editor-preferences
+  editor-preferences? this-editor-preferences
+  (username         editor-preferences-username
+                    (innate)
+                    (sanitize sanitize-username))
+  (background-color editor-preferences-background-color
+                    (default "000000"))
+  (text-color       editor-preferences-text-color
+                    (default "FFFFFF"))
+  (emulation-mode   editor-preferences-emulation-mode
+                    (default #f)
+                    (sanitize sanitize-emulation-mode)))
+@end lisp
+
+There are a couple of differences in the new @code{username} field compare=
d to
+the fields we looked at earlier. It is marked as @code{innate}, which mean=
s
+that it will not be inherited. For example, consider what would happen if =
we
+tried to define new instances like this:
+
+@lisp
+(define my-preferences
+  (editor-preferences
+    (username         "my-username")
+    (background-color "222222")
+    (emulation-mode   'vim)))
+
+(define friends-preferences
+  (editor-preferences
+    (inherit my-preferences)
+    (emulation-mode 'emacs)))
+@end lisp
+
+While the @code{friends-preferences} instance still inherits the values fo=
r
+@code{background-color} and @code{text-color}, it will not inherit the val=
ue
+for @code{username}. Furthermore, as the @code{username} field does not de=
fine
+a default value the attempted creation of @code{friends-preferences} will
+actually throw an error. Instead, we could do this:
+
+@lisp
+(define my-preferences
+  (editor-preferences
+    (username         "my-username")
+    (background-color "222222")
+    (emulation-mode   'vim)))
+
+(define friends-preferences
+  (editor-preferences
+    (inherit        my-preferences)
+    (username       "friends-username")
+    (emulation-mode 'emacs)))
+@end lisp
+
+@node @code{define-record-type*} Reference
+@subsection @code{define-record-type*} Reference
+@defmac define-record-type* name syntactic-constructor constructor predica=
te this-identifier fields ...
+
+Define a new record type and associated helpers.
+
+@table @var
+@item name
+A symbol used to name the type, as would normally be provided to a plain
+@code{define-record-type} form. For example, @code{<package>}.
+
+@item syntactic-constructor
+A symbol that will be used to define the user-facing constructor. For exam=
ple,
+the symbol @code{package} is the syntactic constructor for the @code{<pack=
age>}
+structure.
+
+@item constructor
+A symbol that will be used to define the traditional constructor. It is us=
ed in
+the implementation of the syntactic constructor, but will not typically be=
 used
+elsewhere. The traditional @code{make-name} (for example, @code{make-packa=
ge})
+is a fine value to use here.
+
+@item predicate
+A symbol that will be used to test if a value is an instance of this recor=
d.
+For example, @code{package?}.
+
+@item this-identifier
+This symbol can be used when defining fields that need to refer to the str=
uct
+that contains them. For an example of this, see the @code{thunked} field
+property, below.
+
+@item fields
+A set of field specifiers which take the following form:
+
+@lisp
+(field-name field-getter properties ...)
+@end lisp
+
+Each of the properties must have one of the following forms:
+
+@table @code
+@item (default @var{value})
+Defines the default value for the field, if the user does not specify one =
using
+the syntactic constructor.
+
+@item (innate)
+Fields marked as innate will not be inherited from parent objects (see
+Instantiating Records, below, for details of object inheritance).
+
+@item (sanitize @var{proc})
+The value given by the user will be passed into @var{proc} before being st=
ored
+in the object. For example, consider this struct definition:
+
+@lisp
+(define-record-type* <thing> thing make-thing
+  thing?
+  this-thing
+  (name  thing-name
+         (sanitize (lambda (value)
+                     (cond ((string? value) value)
+                           ((symbol? value) (symbol->string value))
+                           (else (throw 'bad! value)))))))
+@end lisp
+
+When creating @code{thing} instances either a string or a symbol can be
+supplied but it will always be stored as a string:
+
+@lisp
+(string? (thing-name (thing (name "some-name"))))
+@result{} #t
+(string? (thing-name (thing (name 'some-name))))
+@result{} #t
+(thing (name 1994))
+@result{} Throw to key `bad!' with args `(1994)'.
+@end lisp
+
+@item (thunked)
+Fields marked as @code{thunked} will actually compute the field's value in=
 the
+current dynamic extent which is useful when referring to fluids in a field=
's
+value. Furthermore, that thunk can access the record it belongs to via the
+@code{this-identifier}. For example:
+
+@lisp
+(define-record-type* <rectangle> rectangle make-rectangle
+  rectangle?
+  this-rectangle
+  (width  rectangle-width)
+  (height rectangle-height)
+  (area rectangle-area (thunked)
+                       (default (* (rectangle-width  this-rectangle)
+                                   (rectangle-height this-rectangle)))))
+
+(define base-rectangle
+  (rectangle
+    (width  2)
+    (height 4)))
+
+(define derived-rectangle
+  (rectangle
+    (inherit base)
+    (width   6)))
+
+(rectangle-area base-rectangle)
+@result{} 8
+
+(rectangle-area derived-rectangle
+@result{} 24
+@end lisp
+
+@item (delayed)
+Fields marked as @code{delayed} are similar to @code{thunked} fields, exce=
pt
+that they are effectively wrapped in a @code{(delay @dots{})} form. Note t=
hat
+delayed fields cannot use @code{this-identifier}.
+@end table
+@end table
+@end defmac
+
 @node Invoking guix repl
 @section Invoking @command{guix repl}
=20
--=20
2.41.0






Message sent to guix-patches@HIDDEN:


X-Loop: help-debbugs@HIDDEN
Subject: [bug#67786] doc: Add documentation for define-record-type*
Resent-From: Skyler Ferris <skyvine@HIDDEN>
Original-Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
Resent-CC: guix-patches@HIDDEN
Resent-Date: Sat, 13 Jan 2024 18:58:01 +0000
Resent-Message-ID: <handler.67786.B67786.170517227523403 <at> debbugs.gnu.org>
Resent-Sender: help-debbugs@HIDDEN
X-GNU-PR-Message: followup 67786
X-GNU-PR-Package: guix-patches
X-GNU-PR-Keywords: patch
To: 67786 <at> debbugs.gnu.org
Received: via spool by 67786-submit <at> debbugs.gnu.org id=B67786.170517227523403
          (code B ref 67786); Sat, 13 Jan 2024 18:58:01 +0000
Received: (at 67786) by debbugs.gnu.org; 13 Jan 2024 18:57:55 +0000
Received: from localhost ([127.0.0.1]:41085 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1rOjCc-00065O-Q8
	for submit <at> debbugs.gnu.org; Sat, 13 Jan 2024 13:57:55 -0500
Received: from mail-40134.protonmail.ch ([185.70.40.134]:50773)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <skyvine@HIDDEN>) id 1rOjCb-000658-Kd
 for 67786 <at> debbugs.gnu.org; Sat, 13 Jan 2024 13:57:54 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com;
 s=protonmail3; t=1705172268; x=1705431468;
 bh=Wlg008Q6829qkwqfnuF4fsjy8diGO7q3LKzZE2a7VOg=;
 h=Date:To:From:Subject:Message-ID:In-Reply-To:References:
 Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID:
 Message-ID:BIMI-Selector;
 b=MPTzi8Ba/C0C78R3og5CyEuy8fUMoRSKlptjwENuskXEsDiaKJJjPLIqe3XPVH4SG
 EdnXy8+ZynvCisz6ouc8a+4Dqlrgi9fk54TlncfPR+8GcAUPLHRr+LAKt2WrCo4Jjz
 k7FX1GYzMfhjCbc9xXreiWImGGmqPR2zHjZ72Hj0Ig5SmxbHCELERQW4Xw3iZ80Z8X
 GGv6/AkJnStB6/WhyAVnw1CoCGOAeDv0IQ2zgrANgFzqbRU3/8WU9FXs+CuoQQu0Z2
 iPHb5Y6Zktgb9qA6vD5/ONS8WGhNGpH+V/lxkFhJAFHbb9p+da4evWi0tRovGHg8CP
 Z2KxHg69fms3w==
Date: Sat, 13 Jan 2024 18:57:30 +0000
From: Skyler Ferris <skyvine@HIDDEN>
Message-ID: <db1f88f9-6f2e-4353-ae1f-d6080c236097@HIDDEN>
In-Reply-To: <43d0fdc9635394538ffee724beebe885d357bc59.1703713111.git.skyvine@HIDDEN>
References: <43d0fdc9635394538ffee724beebe885d357bc59.1703713111.git.skyvine@HIDDEN>
Feedback-ID: 40635331:user:proton
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
X-Spam-Score: -0.0 (/)
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

Looks like it worked this time! I updated my configuration to send the=20
mail through my provider's servers instead of running exim locally.






Last modified: Sat, 20 Jan 2024 12:30:02 UTC

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