Interpolations.jl is written the way it is such that you can obtain a specialized type that takes advantage of multiple dispatch for subsequent operations.
In terms of type stability, you want to get a consistent output type for a set of input types. Sometimes this means encoding some values as types. For a quick way to do so, see Val
.
I suggest that you use tools like @code_warntype
, @code_lowered
, @code_llvm
, and @code_native
to explore what the compiler is doing.
Let’s take a simple example:
julia> f(x) = 5 + 5
f (generic function with 1 method)
julia> @code_lowered f(1)
CodeInfo(
1 ─ %1 = 5 + 5
└── return %1
)
julia> @code_llvm f(1)
; @ REPL[125]:1 within `f'
; Function Attrs: uwtable
define i64 @julia_f_3722(i64) #0 {
top:
ret i64 10
}
julia> @code_native f(1)
.text
; ┌ @ REPL[125]:1 within `f'
pushq %rbp
movq %rsp, %rbp
movl $10, %eax
popq %rbp
retq
nopl (%rax,%rax)
; └
Above we see that LLVM has figured out that it can precompute 5 + 5
and the assembly shows that the function just returns 10
. It does not add 5 + 5
every time.
!
is used for negation. The only unary operators are listed here:
https://github.com/JuliaLang/julia/blob/master/src/julia-parser.scm#L99-L100