guix-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: A friendlier API for operating-system declarations


From: antlers
Subject: Re: A friendlier API for operating-system declarations
Date: Mon, 19 Feb 2024 14:25:51 -0800
User-agent: Cyrus-JMAP/3.11.0-alpha0-144-ge5821d614e-fm-20240125.002-ge5821d61

Hi!

Just wanted to say that I really admire your take on end-user service 
configuration in the Beaver Labs channel.

I gravitated towards composing functions over `operating-systems` myself, 
though my config is probably only ""notable"" for the moderately-cursed 
`modify-record` macro that I use to derive/configure/wrap the services[1]:

```
(define (os-with-yubi parent users*)
  (modify-record parent
    (groups -> (cons (user-group (name "plugdev")) <>))
    (users  -> (map (lambda (user)
                      (if (member (user-account-name user)
                                  users*)
                          (modify-record user
                            (supplementary-groups -> (cons "plugdev" <>)))
                          user))
                    <>))
    (services => (append <> (list
      (service pcscd-service-type)
      (simple-service 'u2f-udev-rules udev-service-type
                      (list (specification->package "libu2f-host")))
      (simple-service 'yubi-udev-rules udev-service-type
                      (list (specification->package 
"yubikey-personalization"))))))))
```

It's like if `modify-services` was generalized over any kind of record, but 
instead of using pre-defined verbs like `remove`, the `body` component of each 
`(field-name -> body)` clause is wrapped in an implicit SRFI-26 `cut`-like[2] 
form to create an anonymous function that's applied to the field's value. It's 
a super leaky abstraction because I use a different symbol for `->` depending 
on whether that record-field is a plain value, a thunk, or a `delay`-ed form 
(and it could be implemented more efficiently), but it greatly reduces the 
length and indentation level of repeatedly nested, inherited record variations.

```
((compose os-with-yubi
          [...])
   [operative-system])
```

I only wrote a handful of top-level `operating-system transformation` 
functions, and IIRC I only composed them at that top level; I think the way 
that you've broken them up into smaller forms and composed them out of each 
other though deeper, standard-functional composition gives you that same 
additive benefit over would-be nested forms, with each definition roughly 
matching up to one my "anonymous" invocations.

What I still dwell on is whether there's a way to further minimize the 
code-volume of including additional functionality (as was pondered in a prior 
response, and as `modify-record` does in obsoleting `modify-services`'s verbs), 
and how best to avoid order-dependencies and expose inherit 
inter-service-configuration dependencies and conflicts. Tropin's RDE uses an 
emacs or systemd-esque `provides`/`requires` system which is satisfying, but 
introduces implicit standardization on the symbols associated with software 
roles and builds a significant graph of them, which I feel adds to the "bulk" 
of the (still very elegant) solution and embraces the need to wrap every 
service and transformation into their cohesive system-- that's part of what's 
kept me on plain Guix with my bandaid-solutions (in the spirit of learning the 
standard approach before exploring larger systems built on top of it).

Anyway, I like your take, just fount it today and got to thinking-- thanks for 
putting it out there~

1: From: 
https://github.com/AutumnalAntlers/old-guix-config/blob/main/modules/antlers/systems/transformations/yubi.scm
2: Like `cut`, but deeper: see the `<>` symbol nested deep within in the 
`users` clause of the Yubi example.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]