I guess this vector is a hash key but I don’t figure out what happen on #undef. I thought it would be missing or nothing
what does the actual meaning of #undef ?
Can I define a vector like Dict(:x=>1,2=>3,0=>1).keys directly?
Can I define an isolated #undef?
what is the best modification of below code? I thought the code has semantic significant, but it throw error because of #undef. Will Julialang adapt this situation in future?
julia> for i in Dict(:x=>1,2=>3,0=>1).keys
print(i)
end
0ERROR: UndefRefError: access to undefined reference
Stacktrace:
[1] getindex
@ ./array.jl:924 [inlined]
[2] iterate
@ ./array.jl:898 [inlined]
[3] top-level scope
@ ./REPL[9]:3
#undef simply stands for a reference that hasn’t been specified yet. See the following example:
julia> x = Vector{Int}(undef, 3)
3-element Vector{Int64}:
139777823454816
139777979780016
0
julia> y = Vector{String}(undef, 3)
3-element Vector{String}:
#undef
#undef
#undef
Initializing a vector with undef means that we don’t specify its content yet.
In the case of an Int eltype, the vector knows the size (in bytes) of its elements and “reserves” it, but since we haven’t written anything it still contains whatever was there in memory before. Hence the seemingly random numbers, which may be different if i do it again.
But in the case of a String eltype, the vector doesn’t know the size of its elements, so it just stores an undef for each one.
Regarding 4, it is generally considered bad practice to access struct fields directly. Especially in the standard library, there are usually “getters” / “setters” that can help you do that cleanly. And sure enough:
julia> for i in keys(Dict(:x=>1,2=>3,0=>1))
println(i)
end
0
2
x
The reason why your 3-element Dict already has a vector of keys of length 16 probably has to do with efficiency: to achieve an amortized cost of O(1), you don’t want to extend your storage every time you insert a new element, so instead you plan for slightly larger than you need.
I regarded #undef as a memory area that null pointer points in C and Dict(:x=>1,2=>3,0=>1).keys above is a null pointer. Is it right?
I have wrong expression before. In fact I want to ask “Can we define a variable which has value #undef?”.
Well, no. #undef is some marker showing Julia runtime that an access to an array element or a struct field is invalid. It is not a value because you cannot assign it to a variable, check its type etc.
In terms of your specific case, you shouldn’t use Dict(...).keys. Think of it as of an undocumented feature that can change in any version however the devs like. The proper API to access dictionaries is via functions: keys(dict), values(dict), dict[:x] (which is internally translated into a function call getindex(dict, :x)) etc.
yes, I have same paraphrase. #undef is not a value but a placeholder. It means this place (a slot of array or a struct) is not defined. That’s why I said a name like a which didn’t assign is a similar one.
Maybe there are little different between UndefRefError and UndefVarError but I think it’s not important. in u=Vector(undef, 2), u[1] itself is also not define. The Ref just means the vector u have a slot at this place.
if we define u=Vector(undef, 2) we have defined u but didn’t defined u[1] and u[2]. However, to show a vector like
2-element Vector{Int64}:
xxx
xxx
we must have a placeholder at xxx, so there is a #undef. Even through u[1] is undefined, it has a relation with a defined vector u so that the error is UndefRefError .
I don’t think I fully agree. With UndefRef, u or u[1] are both defined, but the values they refer to are not. With UndefVar it is the name (not the value) which is undef.
There’s a difference between an name and a value that you are not completely catching onto. (Leaving aside that u[1] syntax and not just an identifier).
Sorry for my late reply. I might understand and agree what you said, but there are something I want to tell.
Let’s clear some different concepts in my view:
value: some data saved in memory
pointer(in C): the address of memory about the value
reference: an abstraction of pointer
name: a symbol(or a string or an identifier), binding to a reference
It’s a little ambiguous that we say
There are different levels. For a, it’s totally undefined. For u, it certainly defined on every level.
For u[1], it doesn’t have value and we regarded it as a syntax so it doesn’t have name. By error message undefined reference undefined reference and julia source code, it doesn’t have reference and pointer pointed to u[1].