From: Joshua Branson <jbranso@dismail.de>
To: help-guix@gnu.org
Subject: When and how should one use "(thunked)" from (guix records)?
Date: Tue, 19 Oct 2021 04:38:12 -0400 [thread overview]
Message-ID: <87bl3lxvd7.fsf@dismail.de> (raw)
Hey guix! I'm trying to flush out the (guix records) for the
=opensmtpd-service=. It's super fun doing it by the way. If you've
never messed with (guix records) then you should totally give it a
try. Thanks for the author of (guix records). You did a really great
job! The purpose of this email is to get some suggestions on my
opensmtpd-records.scm file and to use this email as a VERY ROUGH draft
for a (guix records) blog post, if there is interest in it. :)
The code that I have so far can be seen here:
https://notabug.org/jbranso/linode-guix-system-configuration/src/master/opensmtpd-records.scm
I'm open to suggestions. :)
I have a basic procedure that turns a <opensmtpd-configuration> into a string...
(define (opensmtpd-configuration->string record)
...)
I've had a ton of fun using the =(thunked)= bit in records. The
documentation in the source code says something like this (also does
the guix manual document guix records somewhere?).
#+BEGIN_EXAMPLE
The 'port' field is \"thunked\", meaning that calls like '(thing-port x)' 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 'this-thing' identifier.
#+END_EXAMPLE
I've found some "too-clever" ways of using (thunked) that people on
irc mentioned may NOT be wise to use. For example, using (thunked) to
define mutually exclusive fieldnames and a fieldname that returns
another fieldnames value. I think these are not "good" ways of using
(thunked). Anyone have any good ideas for using (thunked)?
Below is some obligatory code.
* This bit of guix records shows off the =(thunked)= and =this-record=.
=(thunked)= lets you refer to the record that is being defined. In
this case, I am defining mutually exclusive fieldnames...If =relay= is
defined, then =local-delivery= returns =#f= as its value, which is
pretty awesome.
*Note*: a simpler way to define a mutually exclusive fieldnames is to
have one fieldname that accepts =<cat-record>= or =<dog-record>=.
#+BEGIN_SRC scheme
(define-record-type* <opensmtpd-action>
opensmtpd-action make-opensmtpd-action
opensmtpd-action?
this-record
(name opensmtpd-action-name
(default "local"))
(relay opensmtpd-action-relay
(default "#f")
(local-delivery opensmtpd-action-local-delivery ;;type <opensmtpd-local-delivery-configuration>
;; local-delivery has a default value so (service opensmtpd-service) will just work for
;; local email delivery
(default (opensmtpd-local-delivery-configuration))
(thunked)
(sanitize (lambda (value)
(cond
;; if relay has a value, then local-delivery should be #f
;; man (guix records) rocks!
;; TODO/FIXME, perhaps I should merge fieldnames 'relay', 'local-delivery', 'forward-only',
;; and 'expand-only' into one fildname called "method". Then the user has to use a specific
;; record type to be mutually exclusive.
[(opensmtpd-action-relay this-record)
#f]
[(opensmtpd-local-delivery-configuration? value)
value]
[else
(display (string-append "<opensmtpd-action> fieldname 'local-delivery' "
"needs to be of type <opensmtpd-local-delivery-configuration>.\n"))
(throw 'bad! value)])))))
#+END_SRC
* This bit of guix records defines a fieldname which returns the type of another fieldname
Fieldname =type= returns the type of values that =values= has either
='list-of-strings= or ='assoc-list=.
*Note*: It is probably better to define a function outside of the
record that returns the type that value is. That just makes it
conceptually easier for the next hacker.
#+BEGIN_SRC scheme
(define-record-type* <opensmtpd-table>
opensmtpd-table make-opensmtpd-table
opensmtpd-table?
this-record
;; string
;; is a list of values or key values
;; eg: (list "mysite.me" "your-site.com")
;; eg: (list ("joshua" . "joshua@gnu.org") ("james" . "james@gnu.org"))
(values opensmtpd-table-values
(default #f)
(sanitize (lambda (value)
(if (or (list-of-strings? value)
(assoc-list? value))
value
(begin
(display "<opensmtpd-table> fieldname: 'value' must be a list of strings or an association list.\n")
(throw 'bad! value))))))
;; can be of type: (quote list-of-strings) or (quote assoc-list)
;; type is discovered during the initialition phase. The user SHOULD NEVER set the type.
;; TODO jpoiret: on irc reccomends that I just use an outside function to determine fieldname 'values', type.
;; it would be "simpler" and possibly easier for the next person working on this code to understand what is happening.
(type opensmtpd-table-type
(default #f)
(thunked)
(sanitize (lambda (value)
(if (list-of-strings? (opensmtpd-table-values this-record))
(quote list-of-strings)
(quote assoc-list))))))
#+END_SRC
* I found this is the guix source code...I'm not sure what the (thunked) offers...
#+BEGIN_SRC scheme
;; Configuration of an Xorg server.
(define-record-type* <xorg-configuration>
xorg-configuration make-xorg-configuration
xorg-configuration?
(modules xorg-configuration-modules ;list of packages
(thunked)
; filter out modules not supported on current system
(default (filter
(lambda (p)
(member (%current-system)
(package-supported-systems p)))
%default-xorg-modules)))
(fonts xorg-configuration-fonts ;list of packges
(default %default-xorg-fonts))
(drivers xorg-configuration-drivers ;list of strings
(default '()))
(resolutions xorg-configuration-resolutions ;list of tuples
(default '()))
(keyboard-layout xorg-configuration-keyboard-layout ;#f | <keyboard-layout>
(default #f))
(extra-config xorg-configuration-extra-config ;list of strings
(default '()))
(server xorg-configuration-server ;package
(default xorg-server))
(server-arguments xorg-configuration-server-arguments ;list of strings
(default %default-xorg-server-arguments)))
#+END_SRC
reply other threads:[~2021-10-19 8:38 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://guix.gnu.org/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87bl3lxvd7.fsf@dismail.de \
--to=jbranso@dismail.de \
--cc=help-guix@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).