continues in a 1-iteration loop acting like @gotos to 1 @label because break wasn’t bad enough
function foo(A)
for _ in 1
if is1(A) continue end # @goto wrapup
bar1!(A)
if is2(A) continue end # @goto wrapup
bar2!(A)
end # @label wrapup
baz(A)
end
Unary +/- has high precedence, so it binds to the argument in a nested way. Specifically,
julia> Meta.parse("+ - + 1")
:(+(-(+1)))
Note that I am not blaming Julia for my =- mixup, I think it is perfectly OK to parse that. One cannot expect the parser to catch all mistakes, I should have been writing unit tests for seemingly simple building blocks too.
To clarify, this occurs without the struct X return 1 end too, and it doesn’t make a method according to methods(foo). As far as I can tell from Meta.@lower, it’s the same behavior as early returns from a much less cursed let block, and early returns are treated the same as any other code in local scopes.
The right hand side of the where introduces a new binding. You don’t necessarily need to use it:
julia> Int where asdf
Int64
This is introducing lots of unused where bindings. The only thing that needs to be defined — either by an existing binding or one of the newly introduced ones with the wheres — is the leftmost one.
julia> A where A
Any
julia> Meta.@lower A where A
:($(Expr(:thunk, CodeInfo(
@ none within `top-level scope`
1 ─ %1 = Core.TypeVar(:A)
│ A = %1
│ %3 = Core.UnionAll(A, A)
└── return %3
))))
I’m pretty sure that’s a nothingburger because involving curly braces makes apply_type throw an error if a parameter tries to be the parametric type:
julia> A{Int} where A
ERROR: TypeError: in Type{...} expression, expected UnionAll, got a value of type TypeVar
Stacktrace:
[1] top-level scope
@ REPL[63]:1
julia> Meta.@lower A{Int} where A
:($(Expr(:thunk, CodeInfo(
@ none within `top-level scope`
1 ─ %1 = Core.TypeVar(:A)
│ A = %1
│ %3 = A
│ %4 = Core.apply_type(A, Int)
│ %5 = Core.UnionAll(%3, %4)
└── return %5
))))
As for the sequence of wheres, some of them are not the keyword where, just variables:
julia> where where where
Any
julia> Meta.@lower where where where
:($(Expr(:thunk, CodeInfo(
@ none within `top-level scope`
1 ─ %1 = Core.TypeVar(:where)
│ where = %1
│ %3 = Core.UnionAll(where, where)
└── return %3
))))
sqrt_second(x) = try
sqrt(x[2])
catch y
if isa(y, DomainError)
sqrt(complex(x[2], 0))
elseif isa(y, BoundsError)
sqrt(x)
end
end
sqrt_second([1,"2",3]) # no problemo!
The way error handling works in julia and that you have to explicitly re-throw errors makes me nervous and angry every time I have to do it.
Python has switch-like error handling where you can do
try:
# some error code
except ExpectedErrorType:
# handle that exception
except AnotherErrorType:
# another way to handle error
If the error is not one of ExpectedErrorType or AnotherErrorType, Python falls back to rethrowing the error. It is considered bad practice in Python to do except: and generically handle all exceptions.
Coming from Python, I had similar friction with Julia’s try-catch syntax.