guile-user
[Top][All Lists]
Advanced

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

Exception with multiple irritants


From: Zelphir Kaltstahl
Subject: Exception with multiple irritants
Date: Fri, 25 Nov 2022 00:03:24 +0000

Hello Guile Users!

I have a question regarding exception creation in general and maybe in specific about irritants.

I created a new exception type:

~~~~
(library (exceptions)
  (export make-contract-violated-exception-plain
          make-exception-contract-violated-compound
          &contract-violated
          contract-violated-exception?)
  (import (except (rnrs base) let-values)
          (only (guile)
                lambda* λ
                record-constructor
                make-exception-type
                &programming-error)
          (ice-9 exceptions))

  ;; Create a custom exception type, to make it clearer,
  ;; that a contract failed, and not only an arbitrary
  ;; assertion.
  (define &contract-violated
    (make-exception-type
     ;; name of the new exception type
     '&contract-violated
     ;; parent exception type
     &programming-error
     ;; list of values the constructor of the exception
     ;; takes and their names in the record
     '()))

  (define make-contract-violated-exception-plain
    ;; record-constructor is a procedure, which will return
    ;; the constructor for any record.
    (record-constructor
     ;; Create an exception type, which is a record. This
     ;; record has a constructor, which we can name using
     ;; define for example.
     &contract-violated))

  (define contract-violated-exception?
    (exception-predicate &contract-violated))

  (define make-exception-contract-violated-compound
    (λ (message origin irritants)
      (make-exception
       (make-contract-violated-exception-plain)
       (make-exception-with-message message)
       (make-exception-with-origin origin)
       (make-exception-with-irritants irritants)))))
~~~~

However, I realized, when a contract is violated, it would be nice to not only see the violated contract or condition as irritants, but also the values of the irritants. So I simply tried adding them as well in the exception:

~~~~
...
(define make-exception-contract-violated-compound
    (λ (message origin irritants irritant-values)
      (make-exception
       (make-contract-violated-exception-plain)
       (make-exception-with-message message)
       (make-exception-with-origin origin)
       (make-exception-with-irritants irritants)
       (make-exception-with-irritants irritant-values))))
...
~~~~

Note, that now I have 2 times `make-exception-with-irritants` in there. This does not cause an error and `exception-irritants` still returns the first irritants, so my tests also all still pass, as I have not tested for there not to be other exception attributes.

For example a violated exception example could look like this:

~~~~
(define-with-contract bla
  (require (> foo 10))
  (ensure (> <?> 0))
  (λ (foo)
    (- 20 foo)))

(bla 10)

ice-9/boot-9.scm:1685:16: In procedure raise-exception:
ERROR:
  1. &contract-violated
  2. &message: "contract violated"
  3. &origin: bla
  4. &irritants: (> foo 10)
  5. &irritants: (> 10 10)
~~~~

Nice! Now I have the value of `foo` in this case as well and that could be useful information in cases, when I get a violated contract unexpectedly.

However, having irritants twice seems a bit weird. Is this something, that is safe to do? Something expected and probably unchanging in future versions of GNU Guile? Or does it merely work by chance?

I could always make another exception type like "exception-with-irritant-values" or something and use that, instead of a second "with irritants" call.

Best regards,
Zelphir

--
repositories:https://notabug.org/ZelphirKaltstahl


reply via email to

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