|
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