The manual states “Tab completion can also help completing fields:”, using the example of UUIDs.
However, I recently found that some symbols are not completed (Where is sparse ldlt? - #2 by skleinbo).
So, does anyone know what are the limitations and how does the completion work (or does not?)?
REPL completion works by looking up what symbols are associated with the object in front of the dot. If a symbol is not part of those associated symbols, completion can’t know about it on its own. In your example, SuiteSparse is extending a function from another module, in this case LinearAlgebra, which means the ldlt symbol is not associated with the module SuiteSparse in the first place, resulting in there not being completion for it.
It’s also not trivial to just make that available anyway, since ldlt doesn’t exist from the POV of the SuiteSparse module in the first place. Writing SuiteSparse.ldlt would have to reference LinearAlgebra.ldlt, which seems very confusing to me.
No, not exactly. Both the function and the method live in LinearAlgebra, the text resulting in the method is just “physically” written in SuiteSparse. REPL completion can look up things that actually end up as part of SuiteSparse, which the method defined for ldlt doesn’t.
No, REPL completion doesn’t know (or care) where things are written in a file, only whether they’re part of the resulting module or not. Files in general are not nearly as important in julia as in other languages like python - they’re not coupled to the module structure or what’s reachable from them in code per se.
julia> include("m1.jl")
Main.m1
julia> include("m2.jl")
Main.m2
julia> Main.m2.
eval f include
julia> Main.m2.f
f (generic function with 2 methods)
julia> Main.m1.
eval f include
julia> Main.m1.f
f (generic function with 2 methods)
shell> cat m1.jl m2.jl
module m1
export f
function f(x::Float64)
x*4
end
end
module m2
import ..m1: f
export f
function f(x::Int64)
f(Float64(x))
end
end
As you can see, completion suggests function methods for f from both module m1 and module m2, even though m2 only defines a method for f. Isn’t that the same situation as for ldlt?
Edit: With a submodule.
julia> include("m3.jl")
WARNING: replacing module m3.
Main.m3
julia> Main.m3.
eval include subm3
julia> Main.m3.subm3.
eval f include
julia> Main.m3.subm3.f
f (generic function with 2 methods)
shell> cat m3.jl
module m3
module subm3
import ...m1: f
export f
function f(x::Int64)
f(Float64(x))
end
end
end
This is where the distinction between “where it’s written” and “where it’s associated with/where the method belongs” lies. It’s written in that file, yes, but that doesn’t necessarily mean that it semantically belongs to that module. It’s similar to when you do
module B
# empty module
end
# Here B.C doesn't work
module A
using ..B
@eval B const C = 1
end
# After this, B.C works
You wouldn’t expect A.C to work, right? The same goes for ldlt of SuiteSparse.
No, because in you’re example you’re reexporting f from m2, which associates the name with m2 as well (and m1 of course already has f associated with it). This is not the case for SuiteSparse - the method is not reexported (the reason for which is possibly due to the method only being added conditionally).
The same goes for your submodule example. The submodule subm3 reexports f (which happens independently of being placed in m3) and thus has the name available, while m3 itself does not. It doesn’t know about any f (function or methods) at all - it only knows about the name subm3.