guix-devel
[Top][All Lists]
Advanced

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

Re: better error messages through assertions


From: Philip McGrath
Subject: Re: better error messages through assertions
Date: Tue, 15 Feb 2022 16:45:11 -0500
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.5.0

Hi,

On 2/14/22 17:32, Ricardo Wurmus wrote:
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.


As a Guix user and contributor, I would love better error messages.

As a Racketeer, I think you're half way to reinventing contracts.

In particular, since the operating system services field is thunked, this example already points to the desirability of higher-order contracts.

Using "contracts" need not initially involve all the bells and whistles of Racket's contract library. For example, higher-order contracts can be implemented with `lambda` in the absence of special runtime support for chaperones and impersonators, as illustrated in [1]. But the Racket community has accumulated a great deal of both theoretical insight and implementation experience in many subtle corners of this problem: I hope Guix can build on that experience.

-Philip

[1]: https://docs.racket-lang.org/guide/Building_New_Contracts.html





reply via email to

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