I love Julia – it’s amazing with the VS Code extension, which solves the problem of not being able to perform the simple task of plotting more than one thing at once. There’s just one thing keeping me from recommending it to anyone: startup/TTFX performance.
It wouldn’t be a problem if I could just start a REPL and include("file.jl")
each time I update my code, but I frequently run into problems with previously defined identifiers overstaying their welcome, including functions that don’t reflect my changes and proceed to cause subtle bugs until I remember to restart my REPL. With the frequency at which I encounter these sorts of bugs, I can’t recommend Julia to someone that wants a deterministic programming language.
The last thing I need when I’m attacking a particularly difficult research task or programming problem is to cripple my mind with the massive amount of mental overhead involved with worrying about whether or not the logically and syntactically valid change I just made will introduce a bug into my program.
From what I’ve read in other topics, we’re extremely unlikely to get a workspace()
replacement, so does anyone have any tips for reducing my startup time? I wrote some macros that output results in a format that is more convenient to me, but I think they’re the reason my startup takes so long.
Thanks for reading, and I look forward to learning more about this incredible language.
My startup.jl
contains the following:
using Revise;
using LinearAlgebra;
using Plots;
# Compact show
macro showc(exs...)
blk = Expr(:block)
for ex in exs
push!(blk.args, :(println($(sprint(Base.show_unquoted,ex)*" = "),
repr(begin local value = $(esc(ex)) end, context = :compact=>true))))
end
isempty(exs) || push!(blk.args, :value)
return blk
end
# Pretty show
macro showp(exs...)
blk = Expr(:block)
for ex in exs
push!(blk.args, :(println($(sprint(Base.show_unquoted,ex)*" = "),
repr(MIME("text/plain"), begin local value = $(esc(ex)) end, context = :limit=>true))))
end
isempty(exs) || push!(blk.args, :value)
return blk
end
# Relatively robust floating-point comparisons
function nearly_equal(
a::T, b::T, rel_tol::T = 128 * eps(T), abs_tol::T = eps(T)
)::Bool where T <: AbstractFloat
# Some handy constants for determining whether the defaults are suitable:
# eps(Float64) = 2.220446049250313e-16
# eps(Float32) = 1.1920929f-7
# eps(Float16) = 0.000977
# floatmin(Float64) = 2.2250738585072014e-308
# floatmin(Float32) = 1.1754944f-38
# floatmin(Float16) = 6.104e-5
# See also: nextfloat e.g. nextfloat(1000.0::Float64) - 1000.0::Float64 =
# 1.1368683772161603e-13
if a == b return true; end
diff = abs(a - b);
norm = min(abs(a) + abs(b), floatmax(T))
return diff < max(abs_tol, rel_tol * norm);
end
# Now make it work on vectors
function nearly_equal(
a::Vector{T}, b::Vector{T}, rel_tol::T = 128 * eps(T),
abs_tol::T = 128 * floatmin(T)
)::Bool where T <: AbstractFloat
if size(a) != size(b) throw(DimensionMismatch("Dimension mismatch.")); end
for i in 1:size(a, 1)
if !nearly_equal(a[i], b[i], rel_tol, abs_tol) return false; end
end
return true;
end