santiagocabrera96

santiagocabrera96

Programming Clojure, Fourth Edition: ex-info should include the cause. (p. 224)

In page 224, the following code is suggested.

(defn load-resource [path]
  (try
    (if (forbidden? path)
      (throw (ex-info "Forbidden resource"
                      {:status 403 :resource path}))
      (slurp path))
    (catch java.io.FileNotFoundException e
      (throw (ex-info "Missing resource"
                      {:status 404 :resource path})))
    (catch java.io.IOException e
      (throw (ex-info "Server error"
                      {:status 500 :resource path})))))

I’ve seen this in practice a lot and not including the cause when catching an exception generates headaches to debug later.

I’d suggest to do a bit of explanation of adding the cause exception to the ex info in the catch clauses like this:

(defn load-resource [path]
  (try
    (if (forbidden? path)
      (throw (ex-info "Forbidden resource"
                      {:status 403 :resource path}))
      (slurp path))
    (catch java.io.FileNotFoundException e
      (throw (ex-info "Missing resource"
                      {:status 404 :resource path}
                      e)))
    (catch java.io.IOException e
      (throw (ex-info "Server error"
                      {:status 500 :resource path}
                      e)))))

This is really useful for me to add context to exceptions that might happen in calling functions on sequences to understand what element failed.

Here’s a dummy example where I can call a function that might throw, and I would want more context on where it failed, and I can add context to the existing ex-info.

(defn randomly-fails []
  (when (> (rand-int 10) 8)
    (throw (ex-info "Randomly failed!" {}))))
(run! #(try (randomly-fails)
            (catch clojure.lang.ExceptionInfo e
              (throw (ex-info (ex-message e)
                              (assoc (ex-data e) :n %)
                              e))))
      (range 100))
=> #'examples.interop/randomly-fails
Execution error (ExceptionInfo) at examples.interop/randomly-fails (form-init16509100671821839256.clj:3).
Randomly failed!
*e
=>
#error
{:cause "Randomly failed!",
 :data {},
 :via [{:type clojure.lang.ExceptionInfo,
        :message "Randomly failed!",
        :data {:n 7},
        :at [examples.interop$eval2303$fn__2304 invoke "form-init16509100671821839256.clj" 6]}
       {:type clojure.lang.ExceptionInfo,
        :message "Randomly failed!",
        :data {},
        :at [examples.interop$randomly_fails invokeStatic "form-init16509100671821839256.clj" 3]}],

Where Next?

Popular Pragmatic Bookshelf topics Top

brianokken
Many tasks_proj/tests directories exist in chapters 2, 3, 5 that have tests that use the custom markers smoke and get, which are not decl...
New
Alexandr
Hi everyone! There is an error on the page 71 in the book “Programming machine learning from coding to depp learning” P. Perrotta. You c...
New
brian-m-ops
#book-python-testing-with-pytest-second-edition Hi. Thanks for writing the book. I am just learning so this might just of been an issue ...
New
AndyDavis3416
@noelrappin Running the webpack dev server, I receive the following warning: ERROR in tsconfig.json TS18003: No inputs were found in c...
New
nicoatridge
Hi, I have just acquired Michael Fazio’s “Kotlin and Android Development” to learn about game programming for Android. I have a game in p...
New
akraut
The markup used to display the uploaded image results in a Phoenix.LiveView.HTMLTokenizer.ParseError error. lib/pento_web/live/product_l...
New
mert
AWDWR 7, page 152, page 153: Hello everyone, I’m a little bit lost on the hotwire part. I didn’t fully understand it. On page 152 @rub...
New
EdBorn
Title: Agile Web Development with Rails 7: (page 70) I am running windows 11 pro with rails 7.0.3 and ruby 3.1.2p20 (2022-04-12 revision...
New
mcpierce
@mfazio23 I’ve applied the changes from Chapter 5 of the book and everything builds correctly and runs. But, when I try to start a game,...
New
dachristenson
I’ve got to the end of Ch. 11, and the app runs, with all tabs displaying what they should – at first. After switching around between St...
New

Other popular topics Top

PragmaticBookshelf
Stop developing web apps with yesterday’s tools. Today, developers are increasingly adopting Clojure as a web-development platform. See f...
New
ohm
Which, if any, games do you play? On what platform? I just bought (and completed) Minecraft Dungeons for my Nintendo Switch. Other than ...
New
Exadra37
Oh just spent so much time on this to discover now that RancherOS is in end of life but Rancher is refusing to mark the Github repo as su...
New
PragmaticBookshelf
Create efficient, elegant software tests in pytest, Python's most powerful testing framework. Brian Okken @brianokken Edited by Kat...
New
mafinar
This is going to be a long an frequently posted thread. While talking to a friend of mine who has taken data structure and algorithm cou...
New
PragmaticBookshelf
Author Spotlight Jamis Buck @jamis This month, we have the pleasure of spotlighting author Jamis Buck, who has written Mazes for Prog...
New
PragmaticBookshelf
Programming Ruby is the most complete book on Ruby, covering both the language itself and the standard library as well as commonly used t...
New
PragmaticBookshelf
A concise guide to MySQL 9 database administration, covering fundamental concepts, techniques, and best practices. Neil Smyth MySQL...
New
PragmaticBookshelf
Lint your docs like code: turn any style guide into enforceable rules with Vale and publish clear, consistent content every time. ...
New
xiji2646-netizen
There’s a GitHub repo at forrestchang/andrej-karpathy-skills that’s sitting at 97.8k stars. It’s a single CLAUDE.md file with four behavi...
New

Sub Categories: