Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

introduce throw=> #19

Closed
wants to merge 15 commits into from
Closed

introduce throw=> #19

wants to merge 15 commits into from

Conversation

robertluo
Copy link

My attempt to introduce a new operator throw=> to expect an exception.

@matthewdowney
Copy link
Owner

matthewdowney commented Mar 2, 2023

Hi there @robertluo , nice to meet you!

I'm not sure I'm interested in supporting more assertion types. My goal here is for the comment forms to look as natural as possible (though I do see how the matcho addition opens the door for this kind of thing).

My first reaction is to encourage doing this in a similar way to #15 — exceptions are just another side effect, after all.

Something like:

^:rct/test
(comment
  (with-ex-map
    (throw (Exception. "ok")))
  ;=>> {:message #"ok"}

  (with-ex-map
    (throw (ex-info "ok" {:number 3})))
  ;=>> {:message #"ok" :data {:number odd?}}
  )

With just a helper macro like:

(defmacro with-ex-map
  "Evaluate `body`, and if it throws an exception, return a 
  map with the exception's type, message, and data (if any). 
  
  Otherwise, return the `body` result."
  [& body]
  `(try
     (do ~@body)
     (catch Exception e#
       {:type    (type e#)
        :message (ex-message e#)
        :data    (ex-data e#)})))

What do you think?

@robertluo
Copy link
Author

Hi Matthew,

Thank you so much for creating RCT. I enjoy the workflow improvement it brings.

I agree that keeping things simple is very important, and introducing new concepts only when necessary. Keeping arrow operators minimum is a natural result of this idea. When trying to catch the expected exception in an arrow sexpr, I checked your code, checking if =>> already supported it.

Considering your idea, here's my opinion:

Thrown exception is just a side effect, there are many ideas treating error just as values, like (https://github.com/adambard/failjure)[failjure] and (https://github.com/fmnoise/flow)[flow], suggests. However, throw is a special form, and more programmers prefer using it; most libraries, including Clojure core, still throw exceptions. I have mixed feelings about it; sometimes, I choose to form an error value (like #: error{: type ...}), and sometimes I throw an ExceptionInfo.

  • The idea of catching exceptions and turning them into value will force users to choose one, and they may not distinguish it if they mix these approaches.
  • RCT's => is just (is (= =>> is just (is (m/assert so if we follow the idea of mimicking clojure.test already well-known concept, (is (thrown? and (is (thrown-with-msg may be easy to be understood.
  • If we catch all exceptions in =>>, we also turn errors (unintentional exception thrown) into failures, which is not consistent with the clojure. test basic concept.
  • =>> is working perfectly now; modifying it to support more features will potentially encourage users to extend it to a swiss knife and make it too complex to maintain.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants