Using `exn->string` from `racket/exn` should usually include context ("stack trace")?
https://docs.racket-lang.org/reference/exns.html#(def._((lib._racket%2Fexn..rkt)._exn-~3estring)) Also there will be more context to see, if in DrRacket or racket-mode you've selected that higher level. p.s. It's probably worth considering that many exceptions are surprises about the world outside the program. File or network ports couldn't be opened, read, written. Files didn't exist, or can't be made not to exist. And so on. A program must deal with those, somehow. Usually the exns will be something the user needs to see in the (G)UI, ideally with a simplified message in their language, then the program can hopefully resume just fine. But -- contract violations aren't like that. They're about some code surprising some other code. I think the only hope here is, run the code enough (before the user ever does) to flush out the bad code assumptions and fix them. Realistically that means having enough automated tests, and running them frequently enough (like on every code commit, or at least push, and you can't merge to master if tests don't pass, etc.). Because, there's rarely any good thing to tell the user, beyond "internal error" + cryptic data for them to give tech support. In some cases, the program is even in a state where it shouldn't continue running and should exit. Taking the "do nothing" branch followed by "do something" might be bad times for the user and their data. For example, not saving new changes they made, is bad -- but it's not as bad as also corrupting previously saved data. Even when it's not that dire, a contract violation usually means there aren't any great choices. I'm sorry if any of that sounds preachy! TL;DR: Although it makes sense for contract violations to be exn:fail:contract, but they're really unlike most exn:fails. Contracts are more like ASSERTs in old school C, and the traditional way to handle assertion failures is to abend. On Sat, Mar 23, 2019 at 4:03 PM Ben Greenman <benjaminlgreen...@gmail.com> wrote: > > On 3/23/19, David Storrs <david.sto...@gmail.com> wrote: > > Alex makes good points, but I'm curious about the original question: Is > > there a straightforward way to tell which function it was whose contract > > was violated, aside from parsing the message? Or, more generally, where a > > specific exception came from? > > For blame errors, it might help to grab the blame object and ask it > some questions. > > ``` > #lang racket > > (module a racket > (provide (contract-out (f (-> symbol? symbol?)))) > (define (f sym) > (symbol->string sym))) > (require 'a) > > (with-handlers ((exn:fail:contract:blame? > (lambda (blame-err) > (define b (exn:fail:contract:blame-object blame-err)) > (printf "bad value = ~s~n" (blame-value b))))) > (f 'X)) > ;; bad value = f > ``` > > Docs: > https://docs.racket-lang.org/reference/Building_New_Contract_Combinators.html#(part._.Blame_.Objects) > > -- > You received this message because you are subscribed to the Google Groups > "Racket Users" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to racket-users+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.