ALWAYS (unconditionally) executes given `run` form and:

Default  kind: `:error`
Default level: `:error`
Returns:
  - If given `run` form succeeds: returns the form's result.
  - If given `run` form throws ANYTHING:
      Calls `error!` with the thrown error and given signal options [2], then
      either returns given (:catch-val opts), or rethrows.

Just a convenience util. For more flexibility use your own `try/catch`.
See `taoensso.encore/try*` for easily catching cross-platform errors.

Examples:

  (catch->error! (/ 1 0))         ; %> {:kind :error, :level :error, :error <caught> ...}
  (catch->error! ::my-id (/ 1 0)) ; %> {... :id ::my-id ...}
  (catch->error!
    {:let  [x "x"] ; Available to `:data` and `:msg`
     :data {:x x}
     :msg  ["My msg:" x]
     :catch-val "Return value iff form throws"}

     (/ 1 0)) ; %> {... :data {x "x"}, :msg_ "My msg: x" ...}

Tips:

  - Test using `with-signal`: (with-signal (catch->error! ...)).
  - Supports the same options [2] as other signals [1].

  - Useful for preventing errors from going unnoticed in futures, callbacks,
    agent actions, etc.!: (future (catch->error ::my-future (do-something)))

See also `error!`.

----------------------------------------------------------------------
[1] See `help:signal-creators` - (`signal!`, `log!`, `event!`, ...)
[2] See `help:signal-options`  - {:keys [kind level id data ...]}
[3] See `help:signal-content`  - {:keys [kind level id data ...]}
[4] See `help:signal-filters`  - (by ns/kind/id/level, sampling, etc.)
