As you can probably tell easily by looking at this message, the
“service” field of the operating system configuration looked something
like this:
(services (append (list a b c %desktop-services) #;oops))
instead of this
(services (append (list a b c) %desktop-services))
This is because INSTANTIATE-MISSING-SERVICES — and FOLD-SERVICES, and
many more — assumes that it is only passed a plain list of services. It
then proceeds to call SERVICE-KIND on what may or may not be a service.
I think we should add simple type checks, something like this:
(define (listof pred)
(lambda (thing)
(and (list? thing) (every pred thing))))
…
(define (assert-type type-check thing message)
(or (false-if-exception (type-check thing))
(report-error (G_ "type error: …\n" message))))
;; Use ASSERT-TYPE in an example procedure.
(define (do-something-with-services services)
(assert-type (listof service?) services
"SERVICES must be a list of <service> values.")
;; Do things…
(map service-kind services))
What do you think? There are many different ways of implementing this
(a new variant of DEFINE that also accepts a type declaration, an assert
like above, a fancier assert that composes a helpful error message by
itself, a separate type declaration that is looked up only when the
corresponding procedure is called in a certain context, etc), but I’d
first like to know if there is consensus that we want something like
this.