[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
When and how should one use "(thunked)" from (guix records)?
From: |
Joshua Branson |
Subject: |
When and how should one use "(thunked)" from (guix records)? |
Date: |
Tue, 19 Oct 2021 04:38:12 -0400 |
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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- When and how should one use "(thunked)" from (guix records)?,
Joshua Branson <=