Thank you Liliana and Attila for the swift and actionable feedback :) Below is a revised proposition.
Here is a minimal working example of an os declaration: ------------------mwe.scm--------------- (use-modules (beaver system) (beaver functional-services) (gnu packages version-control) (gnu services web) (gnu services telephony) (gnu services ssh) (gnu services base) (guix gexp)) (-> (minimal-ovh "osef") (instantiate nginx) (instantiate mumble-server (welcome-text "coucou") (port 64738)) (extend openssh `(("alice" ,(local-file "/home/edouard/.ssh/id_rsa.pub")))) (modify openssh (password-authentication? #f) (allow-empty-passwords? #t)) (remove guix)) ------------------------------------------------------- To see the value of this syntactic sugar, try to replicate this MWE with the standard syntax. It's not horrendous, but it *is* off-putting to many newcomers to git, whereas this sugary piece is more readable for them (sample size of 1, p=0.00000005). Here is the revised functional-services.scm, not yet commited and pushed, and only lightly tested in local containers, but not in production: Advice and comments welcome :) ------------functional-services.scm-------------- (define-module (beaver functional-services) #:use-module (gnu system) #:use-module (gnu services) #:export (instantiate extend modify remove)) (define syntax->string (compose symbol->string syntax->datum)) (define (service-configuration stx service) "Return the syntax one can use to refer to xxx-configuration for the given service" (datum->syntax stx (string->symbol (string-append (syntax->string service) "-configuration")))) (define (service-type stx service) "Return the syntax one can use to refer to xxx-service-type for the given service" (datum->syntax stx (string->symbol (string-append (syntax->string service) "-service-type")))) (define-syntax instantiate (lambda (stx) (syntax-case stx () [(_ os service-name) (with-syntax ([service-type (service-type stx #'service-name)]) #'(begin ((lambda (x) ;; It is wrapped in a lamba to make sure os is ;; evaluated once only. It it wasn't in a labmda, whatever ;; form os is in the calling code would be repeated ;; multiple times, and so if the form was e.g. (some-func ;; os), then some-func would be called multiple times, ;; which may not be desirable. (operating-system (inherit x) (services (cons (service service-type) (operating-system-user-services x))))) os)))] [(_ os service-name forms ...) (with-syntax ([service-type (service-type stx #'service-name)] [service-configuration (service-configuration stx #'service-name)]) #'(begin ((lambda (x) ;; Wrapping in a lambda for the same reasons as above (operating-system (inherit x) (services (cons (service service-type (service-configuration forms ...)) (operating-system-user-services x))))) os)))]))) (define-syntax extend (lambda (stx) (syntax-case stx () [(_ os service-name forms ...) (with-syntax ([service-type (service-type stx #'service-name)]) #'(begin ((lambda (x) (operating-system (inherit x) (services (cons (simple-service (format #f "A ~a extension" (syntax->string #'service-name)) service-type forms ...) (operating-system-user-services x))))) os)))]))) (define-syntax modify (lambda (stx) (syntax-case stx () [(_ os service-name forms ...) (with-syntax ([service-type (service-type stx #'service-name)] [service-configuration (service-configuration stx #'service-name)]) #'(begin ((lambda (x) (operating-system (inherit x) (services (modify-services (operating-system-user-services x) (service-type config => (service-configuration (inherit config) forms ...)))))) os)))]))) (define-syntax remove (lambda (stx) (syntax-case stx () [(_ os service-name forms ...) (with-syntax ([service-type (service-type stx #'service-name)]) #'(begin ((lambda (x) (operating-system (inherit x) (services (modify-services (operating-system-user-services x) (delete service-type))))) os)))]))) ------------------------- Attila Lendvai <att...@lendvai.name> writes: >> (service+ OS SERVICE [CONF]) >> (service- OS SERVICE) >> (modify-service OS SERVICE UPDATE) > > > what would the benefit of generating multiple macros for each service > compared to the above functional API (with 3-4 elements altogether)? > > i could be missing something here, but it seems to be precious little to me > while it costs some extra complexity. > > if i were to add a syntactic abstraction for this, i'd generate a full DSL in > the form of a (modify-operating-system OS [fictional DSL to describe desired > changes]). > > but i don't think the extra complexity justifies any macrology here. > > -- > • attila lendvai > • PGP: 963F 5D5F 45C7 DFCD 0A39