> The value of with-timeout is when ~f ge called, automatically cancel the timer, quite clever.

Also it makes sure the callback cannot be called without checking (cancel timeout) first - so it helps avoid mistakes.

> My initial thought: on-timeout and cancel is quite flexible. Does with-timeout is necessary ? How do you think about it? I raise the question for discussion.

They are flexible, but I think they are a bit difficult to understand. It is an unusual pattern.

Compare:

```clojure
(with-timeout respond 800 (println "Timeout triggered")
  (Thread/sleep (rand-nth [900 700]))
  (respond "Response"))
;; vs
(let [timeout (on-timeout 800 (respond "Timeout triggered"))]
  (Thread/sleep (rand-nth [900 700]))
  (when (cancel timeout)
    (respond "Response")))
```

IMO the `with-timeout` form is easier to understand, less easy to make a mistake with, and shorter. It takes away the boilerplate.


I think it would be nice to offer both `on-timeout` and `with-timeout`. `on-timeout` is more flexible, `with-timeout` is more convenient for async callbacks (like HTTP Kit).

What do you think?