diff mbox series

[bug#63985,v3,04/11] doc: Rewrite define-configuration.

Message ID 3c9e04b336d5627af5167ff3b786918df724f3f6.1687816734.git.mirai@makinata.eu
State New
Headers show
Series Service subsystem improvements | expand

Commit Message

Bruno Victal June 26, 2023, 9:59 p.m. UTC
Rewrite this section to make it easier to document later syntactical
changes.

* doc/guix.texi (Complex Configurations): Rewrite define-configuration
documentation. Fix simple serializer example.
---
 doc/guix.texi | 102 +++++++++++++++++++++-----------------------------
 1 file changed, 42 insertions(+), 60 deletions(-)

Comments

Maxim Cournoyer Oct. 2, 2023, 6:28 p.m. UTC | #1
Hi,

Bruno Victal <mirai@makinata.eu> writes:

> Rewrite this section to make it easier to document later syntactical
> changes.
>
> * doc/guix.texi (Complex Configurations): Rewrite define-configuration
> documentation. Fix simple serializer example.

[...]

> +@item @code{(serializer @var{serializer})}
> +@var{serializer} is the name of a procedure which takes two arguments,
> +the first is the name of the field, and the second is the value
> +corresponding to the field.  The procedure should return a string or
> +@ref{G-Expressions} that represents the content that will be serialized
> +to the configuration file.  If none is specified, a procedure of the
> +name @code{serialize-@var{type}} will be used.
> +
> +An example of a simple serializer procedure:
> +@lisp
> +(define (serialize-boolean field-name value)
> +  (let ((value (if value "true" "false")))
> +    #~(string-append '#$field-name #$value)))
> +@end lisp
> +

I know this is adapted from old code, but shouldn't there be a "=" in
that string-append, between the field name and its value?  Also, using
gexps here seems unnecessary and may confuse the reader.

The rest LGTM!
Bruno Victal Oct. 7, 2023, 2:21 p.m. UTC | #2
On 2023-10-02 19:28, Maxim Cournoyer wrote:
>> +An example of a simple serializer procedure:
>> +@lisp
>> +(define (serialize-boolean field-name value)
>> +  (let ((value (if value "true" "false")))
>> +    #~(string-append '#$field-name #$value)))
>> +@end lisp
>> +
> 
> I know this is adapted from old code, but shouldn't there be a "=" in
> that string-append, between the field name and its value? […]

I think there's no particular meaning for that isolated snippet but I
believe the original author did intend for there to be a "=" symbol as
you have pointed out. I've went ahead and added the “ = ” (with spaces)
variant instead.

> […] Also, using gexps here seems unnecessary and may confuse the reader.

I don't think so because in general you're going to call
`serialize-configuration' which returns a G-Expression so it's more or
less given that using G-Expressions is perfectly valid and using them
from the outset allows your fields to serialize any kind of value such as
package objects (for something like `gcc-path = /gnu/store/…'), etc.

Thus, not using G-Exps is more restrictive in terms of what you can
serialize. It might not make a difference in some cases but I think
this is a potential source of trouble when someone tries to serialize
a gexp object with a non-gexp ready serializer. (e.g. performing
string-append with a string and a package object)

I'm aware of some cases where this is not a problem such as the case
where you write your own version of `serialize-configuration' to
handle the serialization in some other manner. (perhaps using `list'
instead of `string-append' for the final step)
Such a case is clearly in the “advanced guix hacker” arena and thus
I don't think there's a risk for confusion here.
Maxim Cournoyer Oct. 7, 2023, 4:35 p.m. UTC | #3
Hi,

Bruno Victal <mirai@makinata.eu> writes:

> On 2023-10-02 19:28, Maxim Cournoyer wrote:
>>> +An example of a simple serializer procedure:
>>> +@lisp
>>> +(define (serialize-boolean field-name value)
>>> +  (let ((value (if value "true" "false")))
>>> +    #~(string-append '#$field-name #$value)))
>>> +@end lisp
>>> +
>> 
>> I know this is adapted from old code, but shouldn't there be a "=" in
>> that string-append, between the field name and its value? […]
>
> I think there's no particular meaning for that isolated snippet but I
> believe the original author did intend for there to be a "=" symbol as
> you have pointed out. I've went ahead and added the “ = ” (with spaces)
> variant instead.
>
>> […] Also, using gexps here seems unnecessary and may confuse the reader.
>
> I don't think so because in general you're going to call
> `serialize-configuration' which returns a G-Expression so it's more or
> less given that using G-Expressions is perfectly valid and using them
> from the outset allows your fields to serialize any kind of value such as
> package objects (for something like `gcc-path = /gnu/store/…'), etc.
>
> Thus, not using G-Exps is more restrictive in terms of what you can
> serialize. It might not make a difference in some cases but I think
> this is a potential source of trouble when someone tries to serialize
> a gexp object with a non-gexp ready serializer. (e.g. performing
> string-append with a string and a package object)

Agreed.
diff mbox series

Patch

diff --git a/doc/guix.texi b/doc/guix.texi
index 853396f776..8355260378 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -41953,54 +41953,33 @@  Complex Configurations
 files, you can use the utilities defined in the @code{(gnu services
 configuration)} module.
 
-The main utility is the @code{define-configuration} macro, which you
-will use to define a Scheme record type (@pxref{Record Overview,,,
-guile, GNU Guile Reference Manual}).  The Scheme record will be
-serialized to a configuration file by using @dfn{serializers}, which are
-procedures that take some kind of Scheme value and returns a
-G-expression (@pxref{G-Expressions}), which should, once serialized to
-the disk, return a string.  More details are listed below.
+The main utility is the @code{define-configuration} macro, a helper
+used to define a Scheme record type (@pxref{Record Overview,,,
+guile, GNU Guile Reference Manual}).  The fields from this Scheme record
+can be serialized using @dfn{serializers}, which are procedures that take
+some kind of Scheme value and translates them into another Scheme value or
+@ref{G-Expressions}.
 
 @defmac define-configuration name clause1 clause2 @dots{}
 Create a record type named @code{@var{name}} that contains the
 fields found in the clauses.
 
-A clause can have one of the following forms:
+A clause has the following form:
 
 @example
 (@var{field-name}
- (@var{type} @var{default-value})
- @var{documentation})
-
-(@var{field-name}
- (@var{type} @var{default-value})
- @var{documentation}
- (serializer @var{serializer}))
-
-(@var{field-name}
- (@var{type})
- @var{documentation})
-
-(@var{field-name}
- (@var{type})
- @var{documentation}
- (serializer @var{serializer}))
-
-(@var{field-name}
- (@var{type})
+ @var{type-decl}
  @var{documentation}
- (sanitizer @var{sanitizer})
-
-(@var{field-name}
- (@var{type})
- @var{documentation}
- (sanitizer @var{sanitizer})
- (serializer @var{serializer}))
+ @var{option*}
+ @dots{})
 @end example
 
 @var{field-name} is an identifier that denotes the name of the field in
 the generated record.
 
+@var{type-decl} is either @code{@var{type}} for fields that require a
+value to be set or @code{(@var{type} @var{default})} otherwise.
+
 @var{type} is the type of the value corresponding to @var{field-name};
 since Guile is untyped, a predicate
 procedure---@code{@var{type}?}---will be called on the value
@@ -42018,6 +41997,28 @@  Complex Configurations
 @var{documentation} is a string formatted with Texinfo syntax which
 should provide a description of what setting this field does.
 
+@var{option*} is one of the following subclauses:
+
+@table @asis
+@item @code{empty-serializer}
+Exclude this field from serialization.
+
+@item @code{(serializer @var{serializer})}
+@var{serializer} is the name of a procedure which takes two arguments,
+the first is the name of the field, and the second is the value
+corresponding to the field.  The procedure should return a string or
+@ref{G-Expressions} that represents the content that will be serialized
+to the configuration file.  If none is specified, a procedure of the
+name @code{serialize-@var{type}} will be used.
+
+An example of a simple serializer procedure:
+@lisp
+(define (serialize-boolean field-name value)
+  (let ((value (if value "true" "false")))
+    #~(string-append '#$field-name #$value)))
+@end lisp
+
+@item @code{(sanitizer @var{sanitizer})}
 @var{sanitizer} is a procedure which takes one argument,
 a user-supplied value, and returns a ``sanitized'' value for the field.
 If no sanitizer is specified, a default sanitizer is used, which raises
@@ -42031,21 +42032,7 @@  Complex Configurations
         ((symbol? value) (symbol->string value))
         (else (error "bad value"))))
 @end lisp
-
-@var{serializer} is the name of a procedure which takes two arguments,
-the first is the name of the field, and the second is the value
-corresponding to the field.  The procedure should return a string or
-G-expression (@pxref{G-Expressions}) that represents the content that
-will be serialized to the configuration file.  If none is specified, a
-procedure of the name @code{serialize-@var{type}} will be used.
-
-A simple serializer procedure could look like this:
-
-@lisp
-(define (serialize-boolean field-name value)
-  (let ((value (if value "true" "false")))
-    #~(string-append #$field-name #$value)))
-@end lisp
+@end table
 
 In some cases multiple different configuration records might be defined
 in the same file, but their serializers for the same type might have to
@@ -42066,13 +42053,13 @@  Complex Configurations
 
 (define-configuration foo-configuration
   (label
-   (string)
+   string
    "The name of label.")
   (prefix foo-))
 
 (define-configuration bar-configuration
   (ip-address
-   (string)
+   string
    "The IPv4 address for this device.")
   (prefix bar-))
 @end lisp
@@ -42164,11 +42151,6 @@  Complex Configurations
 disk by using something like @code{mixed-text-file}.
 @end deffn
 
-@deffn {Procedure} empty-serializer field-name value
-A serializer that just returns an empty string.  The
-@code{serialize-package} procedure is an alias for this.
-@end deffn
-
 Once you have defined a configuration record, you will most likely also
 want to document it so that other people know to use it.  To help with
 that, there are two procedures, both of which are documented below.
@@ -42271,7 +42253,7 @@  Complex Configurations
 
 (define-configuration contact-configuration
   (name
-   (string)
+   string
    "The name of the contact."
    serialize-contact-name)
   (phone-number
@@ -42281,15 +42263,15 @@  Complex Configurations
    maybe-string
    "The person's email address.")
   (married?
-   (boolean)
+   boolean
    "Whether the person is married."))
 
 (define-configuration contacts-list-configuration
   (name
-   (string)
+   string
    "The name of the owner of this contact list.")
   (email
-   (string)
+   string
    "The owner's email address.")
   (contacts
    (list-of-contact-configurations '())