Hi Sébastien,

Sébastien Gendre <[email protected]> writes:

Hi Ian,

Thank you very much for your reply and your help.
I wrote my replies after the quotes.

Ian Eure <[email protected]> writes:
Sébastien Gendre <[email protected]> writes:
    ;; Define serializer functions
    (define (serialize-luanti-admin-name field-name value)
      "Serialize the Luanti admin name field for the config
file."
      (let ((field-real-name "name"))
        #~(string-append #$field-real-name " = " #$value)))

Since you’re only building strings, you don’t need a gexp, nor do you
need the let binding.  Here’s a simplified version:

   (define (serialize-luanti-admin-name _ value)
"Serialize the Luanti admin name field for the config file."
     (string-append "name = " #$value))

Thank you very much. I'm still very new with gexp. The
`define-configuration' documentation was saying that the serializer procedure should return a gexp. But if it can be done without gexp, that
make it easy.

I think there’s actually a documentation issue, this whole section is worded very strangely. It looks like `@ref{G-Expressions}' is being
represented as "see G-Expressions" in the text for some reason.

The relevant part of the docs is this, though:

The procedure should return a string or *note G-Expressions:: that
   represents the content that will be serialized to the
   configuration file.

Which should properly say "a string or g-expression."


    ;; Define the Luanti Game configuration
    (define-configuration luanti-game-configuration
      (admin-name
       maybe-string
       "Username of the administrator."
       (serializer serialize-luanti-admin-name)))

This is mixing an optional predicate with a required serializer, which won’t work right. While it’s boilerplatey, I find that the best
approach is to make one type per field:

   (define admin-name? string?)
(define (serialize-admin-name field-name value) "do the right
   thing here")

Then use `define-maybe' and the predicate & serializer it expands to:

   (define-maybe admin-name)

   (define-configuration luanti-game-configuration
     (admin-name maybe-admin-name "Username of the
     administrator."))

Within the configuration system, "type" covers both the value *and* how it’s handled, which can cause problems when you have two fields which take string, but need different serialize-string handling --
like one needing to be quoted, or one representing an INI-style
[section] and another a key = value pair. Starting here gives you
clean separation you can merge later, if you like.

I thought that I could use an existing type (string) and only specify a specific serializer for this parameter. An then, define a generic string
serializer for the simple string parameters.

You can. It’s a matter of whether you prefer boilerplate in the form
of (serializer serialize-foo) or (define foo? string?).


When I define a maybe and a serializer procedure for a type, the
serializer procedure didn't have to adapt its behavior based on the
"maybe" part ? Like returning something only if the value is not
empty ?

That’s the problem, your custom serializer doesn’t handle
`%unset-marker', so it won’t serialize unset optional values
correctly. In this case, I think it’s simpler to define a predicate
and serializer for your type, then use `define-maybe'.  The
alternative is adding `%unset-marker' handling to any custom
serializer for an optional field.


I took inspiration of `libvirt-conf-file' (in file
gnu/services/virtualization.scm:486). How is it working in the case
of `libvirt-conf-file' ? Is it only working in the context of a
system service activation ?

The serializers for the fields in libvirt-configuration all use
`(format #t ...)', which prints the output.  I don’t know why it’s
like that, it seems like an approach that isn’t in line with the
intentions of the configuration system.


On a closing note, I’ll share that I’ve also struggled a lot with the
configuration system in Guix, both in its documentation and
implementation. Implementation-wise, the system feels both barebones and verbose. I’ve run into some stuff with unsatisfying expressions,
like fields whose names aren’t needed, config subsections, and
configurations spanning multiple files. These all require workarounds which feel more like subverting the system than using it as intended.

I have the same problem. I have more experience with Ansible and it's template module. I thought that `define-configuration' would serve the same goal but using Scheme programming instead of template. I bit like the HTML export backend of Org-mode is, compared to usual template
system of static and dynamic web pages generators.

Yeah, it’s not a system like that at all.  The goal is to insulate
users of the configuration records you define from the details of the underlying program’s file format. That allows the whole system to be configured entirely with Scheme. It’s like creating Python classes representing the whole configuration, and a mechanism to convert those
to the text file representation the program expects.


On the documentation side, the Guix manual is an invaluable reference, but a lot of it feels like just that -- a reference. It has great "what" and "how" information, but in my opinion, sorely lacks the
contextual "why" and "when" to effectively apply it.

Yes, I get what you mean about the manual. I think the contextual "why" and "when" is more in the cookbook. But, for now, there is no section about writing a system service step by step. Or a home service. I would love to help, but my actual understanding of it is not a the required
level to write a good tutorial.

The cookbook has some good stuff, but doesn’t seem like it’s always as
up-to-date as the manual.


And, about the manual, I noticed that as a new Guix and Guix system user, I have some difficulties to understand some parts. It's like I miss an information, or a details, in the manual. But I didn't note it somewhere, so now it would be difficult to notice it again. At least,
for parts I understand now.

Yes, there are a lot of terms thrown out before they’re defined, or
which have definitions which are hard for new users to understand.

When I’m writing technical documentation, I try my best to define
terms and outline high-level concepts before getting into the
technical details -- having an understanding of the general shape of
the system helps me contextualize the more tecnical stuff.

While I freely admit this is a personal opinion/preference, I’ve found that it seems to be a method of communicating which works for a lot of
people.

 -- Ian

Reply via email to