We should probably not be able to catch the interrupt exception from within the code?
(sci/eval-string "(try (loop [] (recur)) (catch Exception ex :noop))" {:interrupt-fn (limit 100)})
;=> :noopYou cannot do much after I think, but it could hide the interrupt exception or it could be used to test the limits
Yeah I think this should be considered a bug, issue welcome
Throwing a special exception that is ignored in SCI or so can be a solution
PSA: :interrupt-fn now requires you to use sci.interrupt/interrupt! to interrupt evaluation.
(require '[sci.interrupt :as interrupt])
(defn limit [n]
(let [counter (atom 0)]
(fn [] (when (> (swap! counter inc) n)
(interrupt/interrupt!)))))
This solves the problem that a user cannot catch the exception thrown by the :interrupt-fn. Thanks @jeroenvandijk for reporting this problem.
See updated docs. https://github.com/babashka/sci/blob/master/doc/interrupt.md
cc @whiloOk curious what you think about the following below (from https://github.com/babashka/sci/pull/1027)
;; Try the following
;;
;; deps-try instance-methods-control-exp
(require '[sci.core :as sci]
'[sci.interrupt :as interrupt])
(defn pow'
[x exponent]
(when (neg? exponent)
(throw (ArithmeticException. "negative exponent")))
(loop [e exponent
base (bigint x)
acc 1N]
(interrupt/interrupt!)
(if (zero? e)
acc
(recur (quot e 2)
(*' base base)
(if (odd? e)
(*' acc base)
acc)))))
(time
(try
(sci/eval-string "(.pow (biginteger 10) 10000000)"
{:classes {'java.math.BigInteger {:instance-methods {'pow pow'}}}})
(catch Exception e
(println (ex-message e)))))
;; Interrupted
;; "Elapsed time: 1.602208 msecs"
;; => nil Ok curious what you think about the following in this thread (from https://github.com/babashka/sci/pull/1027)
;; Try the following
;;
;; deps-try instance-methods-control-exp
(require '[sci.core :as sci]
'[sci.ctx-store :as store]
'[sci.interrupt :as interrupt])
(defn pow'
[x exponent]
(let [interrupt-fn (or (interrupt/get-interrupt-fn (store/get-ctx)) (constantly nil))]
(when (neg? exponent)
(throw (ArithmeticException. "negative exponent")))
(loop [e exponent
base (bigint x)
acc 1N]
(interrupt-fn)
(if (zero? e)
acc
(recur (quot e 2)
(*' base base)
(if (odd? e)
(*' acc base)
acc))))))
(defn time-limit [ms]
(let [deadline (+ (System/nanoTime) (.toNanos java.util.concurrent.TimeUnit/MILLISECONDS ms))]
(fn []
(when (> (System/nanoTime) deadline)
(interrupt/interrupt!)))))
(time
(try
(sci/eval-string "(.pow (biginteger 10) 10000000)"
{:interrupt-fn (time-limit 100)
:classes {'java.math.BigInteger {:instance-methods {'pow pow'}}}})
(catch Exception e
(println (ex-message e)))))
;; Interrupted
;; "Elapsed time: 139.687542 msecs"
;; => nil