|
1 | 1 | const LOGGED_FUN = Set([log, sqrt, (^), /, inv])
|
2 |
| -is_legal(::typeof(/), a, b) = is_legal(inv, b) |
3 |
| -is_legal(::typeof(inv), a) = !iszero(a) |
4 |
| -is_legal(::Union{typeof(log), typeof(sqrt)}, a) = a isa Complex || a >= zero(a) |
5 |
| -is_legal(::typeof(^), a, b) = a isa Complex || b isa Complex || isinteger(b) || a >= zero(a) |
6 | 2 |
|
| 3 | +struct LoggedFunctionException <: Exception |
| 4 | + msg::String |
| 5 | +end |
7 | 6 | struct LoggedFun{F}
|
8 | 7 | f::F
|
9 | 8 | args::Any
|
10 | 9 | end
|
| 10 | +Base.showerror(io::IO, err::LoggedFunctionException) = print(io, err.msg) |
11 | 11 | Base.nameof(lf::LoggedFun) = nameof(lf.f)
|
12 | 12 | SymbolicUtils.promote_symtype(::LoggedFun, Ts...) = Real
|
13 | 13 | function (lf::LoggedFun)(args...)
|
14 |
| - f = lf.f |
15 |
| - symbolic_args = lf.args |
16 |
| - if is_legal(f, args...) |
17 |
| - f(args...) |
18 |
| - else |
19 |
| - args_str = join(string.(symbolic_args .=> args), ", ", ", and ") |
20 |
| - throw(DomainError(args, "$(lf.f) errors with input(s): $args_str")) |
| 14 | + try |
| 15 | + return lf.f(args...) # try to call with numerical input, as usual |
| 16 | + catch err |
| 17 | + throw(LoggedFunctionException( |
| 18 | + "Function $(lf.f)($(join(lf.args, ", "))) errors with input" * |
| 19 | + join("\n " .* string.(lf.args .=> args)) # one line for each "var => val" for readability |
| 20 | + )) # Julia automatically attaches original error message |
21 | 21 | end
|
22 | 22 | end
|
23 | 23 |
|
|
0 commit comments