Clarification:
I’m looking for something similar to: condition ? a : b
Except, my condition is when a
returns some type of error, then do b
instead of a
.
AZ(x)= try; sqrt(x); catch e; return sqrt(complex(x)); end
AZ(2), AZ(-2)
#I want
AZ(a,b)= try; a; catch e; return b; end
AZ(sqrt(-2), sqrt(complex(-2)))
x = try sqrt(-1); catch e; 0 ; end
x is now = 0
I want a function AZ(a,b)
which first does a
and if there is an error doing a
, then does b
.
AZ( a, b) = try sqrt(a) catch; sqrt(b) end
AZ(-1,4)
No such function can ever exist in general because functions evaluate all of their arguments, but you want control flow (like the ternary operator provides), so you need to write a macro. Maybe something like the following:
macro trycatch(a, b)
quote
try
tmp = $(esc(a))
tmp
catch
$(esc(b))
end
end
end
let x = 2
@trycatch(sqrt(x), sqrt(complex(x)))
end
let x = -2
@trycatch(sqrt(x), sqrt(complex(x)))
end
4 Likes
Thanks! Do you know where a?b:c
is in the Julia source code?
Currently I’ve been programming an mle solver where loglik returns -Inf
for illegal parameters:
ll(θ;dist=dist,data=data) = try
-sum(logpdf.(dist{Float64}(θ...),data))
catch e
return Inf
end
I’d prefer an operator like a?$
:
ll(θ;dist=dist,data=data)= -sum(logpdf.(dist{Float64}(θ...),data)) @?$ Inf
What do you mean by that? That’s part of Julia’s syntax: it’s in the parser and isn’t a function whose definition you could read. You could write a macro to reuse that syntax for your own needs if you wanted to.
4 Likes
Also this might be interesting
tryesce(a, b) =
for i in b
tmp = nothing
try
tmp = a(i)
catch
end
tmp === nothing ? continue : return tmp
end
tryesce(sqrt, [-1,-2,4])
To followup w/ the above example (which works great!):
macro trycatch(a, b)
quote
try
tmp = $(esc(a))
tmp
catch
$(esc(b))
end
end
end
#
f1(x)=@trycatch(sqrt(x), sqrt(complex(x)))
f1(2), f1(-2)
is it possible to rewrite: @trycatch(f(x), g(x))
with my own @$@
as follows: f(x) @$@ g(x)
I wasn’t able to find this in the macro docs.
No, there’s no such thing as infix macros in Julia, unfortunately.
2 Likes
But then how do they allow: cond ? a : b
same as ifelse(cond,a,b)
?
They are not the same thing:
julia> true ? println("foo") : println("bar")
foo
julia> ifelse(true, println("foo"), println("bar"))
foo
bar
1 Like
Also note that the ternary operator is a language feature, not a macro. Therefore, it also can’t be redefined by the user.
3 Likes
So bottom line if I have some function:
add(a,b)
I cannot rewrite it as a @$@ b
Functions are very different from macros. You can redefine infix operators, because they are just generic functions. Functions can’t transform syntax though. For example, you can define the infix operator $
:
julia> a $ b = 10 * a + b
$ (generic function with 1 method)
julia> 1 $ 2
12
2 Likes
I think you’re getting fixated on macro being an infix operator, which isn’t possible but shouldn’t matter that much. You can easily do something like @t a $ b
.
3 Likes