How to create constructor with Null argumnet in Julia - julia

I want to create type Family with argument type Family but i want to create possibility with Null argument
type Family
name:: AbstracDtring
people:: Int
dad:: Family
mom:: Family
Family(name:: AbstractString, people::Int ) = new (name, people , NULL, NULL)
end
Can i do somthing with this i want create "object" with references to another object or without references

You can call new with fewer arguments:
type Family
name::AbstractString
people::Int
dad::Family
mom::Family
Family(name::AbstractString, people::Int) = new(name, people)
end
You can construct instances but until you've assigned the .dad and .mom fields, accessing them will cause an error:
julia> fam = Family("Jones", 3)
Family("Jones",3,#undef,#undef)
julia> fam.dad
ERROR: UndefRefError: access to undefined reference
in eval(::Module, ::Any) at ./boot.jl:225
in macro expansion at ./REPL.jl:92 [inlined]
in (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at ./event.jl:46
julia> fam.mom
ERROR: UndefRefError: access to undefined reference
in eval(::Module, ::Any) at ./boot.jl:225
in macro expansion at ./REPL.jl:92 [inlined]
in (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at ./event.jl:46
julia> fam.dad = fam
Family("Jones",3,Family(#= circular reference #-1 =#),#undef)
julia> fam.mom
ERROR: UndefRefError: access to undefined reference
in eval(::Module, ::Any) at ./boot.jl:225
in macro expansion at ./REPL.jl:92 [inlined]
in (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at ./event.jl:46
You can check if a field is defined or not using the isdefined function:
julia> isdefined(fam, :dad)
true
julia> isdefined(fam, :mom)
false
The Nullable approach works too but this is somewhat lighter weight.

Use Nullable (http://docs.julialang.org/en/release-0.4/manual/types/#nullable-types-representing-missing-values)
type Family
name:: AbstractString
people:: Int
dad:: Nullable{Family}
mom:: Nullable{Family}
Family(name:: AbstractString, people::Int ) = new(name, people, Nullable{Family}(), Nullable{Family}())
end

Related

How to lock the variable type in Julia?

I want to lock the type of a variable in Julia, how to do? For example, I define an array called weight,
weight = Array{Float64,1}([1,2,3])
Now I want to lock the type of weight as Array{Float64,1}, is it possible?
I mean if do not lock the type of weight, then if I mistakenly or casually do
weight = 1
Then weight will become an Int64 variable, so it is not longer a 1D array. This is obviously not what I want.
I just want to make sure that once I defined weight as 1D Float64 array, then if I change the type of weight, I want Julia gives me an error saying that the type of weight has been changed which is not allowed. Is it possible? Thanks!
This is useful because by doing this, it may preventing me from forgetting weight is an 1D array, and therefore preventing bugs.
For global variables use const:
julia> const weight = Array{Float64,1}([1,2,3])
3-element Vector{Float64}:
1.0
2.0
3.0
julia> weight[1]=11
11
julia> weight=99
ERROR: invalid redefinition of constant weight
Note that redefining the reference will throw a warning:
julia> const u = 5
5
julia> u=11
WARNING: redefinition of constant u. This may fail, cause incorrect answers, or produce other errors
You can circumvent it by using the Ref type:
julia> const z = Ref{Int}(5)
Base.RefValue{Int64}(5)
julia> z[] = 11
11
julia> z[] = "hello"
ERROR: MethodError: Cannot `convert` an object of type String to an object of type Int64
In functions use local with type declaration:
julia> function f()
local a::Int
a="hello"
end;
julia> f()
ERROR: MethodError: Cannot `convert` an object of type String to an object of type Int64
You'd normally write:
weight::Vector{Float64} = Array{Float64,1}([1,2,3])
...but this doesn't seem to be possible in global scope:
julia> weight::Vector{Float64} = Array{Float64,1}([1,2,3])
ERROR: syntax: type declarations on global variables are not yet supported
Stacktrace:
[1] top-level scope
# REPL[8]:1
However, you can do it in local scope or in a struct:
julia> function fun()
weight::Vector{Float64} = Array{Float64,1}([1,2,3])
weight = 1
end
fun (generic function with 1 method)
julia> fun()
ERROR: MethodError: Cannot `convert` an object of type Int64 to an object of type Vector{Float64}
Closest candidates are:
convert(::Type{T}, ::AbstractArray) where T<:Array at array.jl:532
convert(::Type{T}, ::LinearAlgebra.Factorization) where T<:AbstractArray at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/factorization.jl:58
convert(::Type{T}, ::T) where T<:AbstractArray at abstractarray.jl:14
...
Stacktrace:
[1] fun()
# Main ./REPL[10]:3
[2] top-level scope
# REPL[11]:1
You could use const, but then redefinition with a value of the same type will cause a warning:
julia> const weight = Array{Float64,1}([1,2,3]);
julia> weight = [2.]
WARNING: redefinition of constant weight. This may fail, cause incorrect answers, or produce other errors.
1-element Vector{Float64}:
2.0

How do I parse a string to a float or int in Julia?

I am trying to take a string a = "99.99" and then convert it to be of type float. On top of that, I want to be able to convert a to an int as well. How can I do that? The built-in int() and float() functions don't appear to take strings.
julia> a = "99.99"
"99.99"
julia> float(a)
ERROR: MethodError: no method matching AbstractFloat(::String)
Closest candidates are:
AbstractFloat(::Bool) at float.jl:252
AbstractFloat(::Int8) at float.jl:253
AbstractFloat(::Int16) at float.jl:254
...
Stacktrace:
[1] float(::String) at ./float.jl:271
[2] top-level scope at REPL[2]:1
julia> Int(a)
ERROR: MethodError: no method matching Int64(::String)
Closest candidates are:
Int64(::Union{Bool, Int32, Int64, UInt32, UInt64, UInt8, Int128, Int16, Int8, UInt128, UInt16}) at boot.jl:710
Int64(::Ptr) at boot.jl:720
Int64(::Float32) at float.jl:700
...
Stacktrace:
[1] top-level scope at REPL[3]:1
Inspired by this post.
You can use the parse(::Type{T}, ::AbstractString) function, like so:
julia> parse(Float64, "1")
1.0

ERROR: MethodError: no method matching ccolor(::Type{ColorTypes.Gray{FixedPointNumbers.Normed{UInt8,8}}}, ::Type{Nothing}) in Julia

I get the following error when loading maps in Julia:
ERROR: MethodError: no method matching ccolor(::Type{ColorTypes.Gray{FixedPointNumbers.Normed{UInt8,8}}}, ::Type{Nothing})
Closest candidates are:
ccolor(::Type{Cdest<:ColorTypes.Colorant}, ::Type{Csrc<:ColorTypes.Colorant}) where {Cdest<:Colorant, Csrc<:Colorant} at /Users/logankilpatrick/.julia/packages/ColorTypes/BsAWO/src/traits.jl:259
ccolor(::Type{Cdest<:(ColorTypes.Color{T,1} where T)}, ::Type{T<:Number}) where {Cdest<:(Color{T,1} where T), T<:Number} at /Users/logankilpatrick/.julia/packages/ColorTypes/BsAWO/src/traits.jl:260
Stacktrace:
[1] convert(::Type{ColorTypes.Gray{FixedPointNumbers.Normed{UInt8,8}}}, ::Nothing) at /Users/logankilpatrick/.julia/packages/ColorTypes/BsAWO/src/conversions.jl:7
[2] ColorTypes.Gray{FixedPointNumbers.Normed{UInt8,8}}(::Nothing) at /Users/logankilpatrick/.julia/packages/ColorTypes/BsAWO/src/types.jl:446
[3] _broadcast_getindex_evalf at ./broadcast.jl:574 [inlined]
[4] _broadcast_getindex at ./broadcast.jl:547 [inlined]
[5] getindex at ./broadcast.jl:507 [inlined]
[6] copy at ./broadcast.jl:734 [inlined]
[7] materialize(::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{0},Nothing,Type{ColorTypes.Gray{FixedPointNumbers.Normed{UInt8,8}}},Tuple{Base.RefValue{Nothing}}}) at ./broadcast.jl:724
The error references a function I use called loadgraymap defined as follows: loadgraymap(filename::String) = Gray{N0f8}.(FileIO.load(filename)) |> transpose
It interestingly works the first time it is called but doesn't work the 2nd time it's called. Any advice on how to fix this issue? I do not have any problem with v0.6 of Julia. I also get the following warning: WARNING: QuartzImageIO: indexed color images not implemented but I am unsure what it means
Here is where I call the method:
holderVar.zone_map = loadcolormap(map_file_name(sim_params, "Zone"))
holderVar.depth_map = loadgraymap(map_file_name(sim_params, "Depth"))
#temp_slope_map = loadgraymap(map_file_name(sim_params, "Slope"))
#holderVar.slope_map = (someFakeNum/someFakeNum) .* (someFakeNum .- temp_slope_map)
#temp_elev_map = loadgraymap(map_file_name(sim_params, "Elevation"))
#holderVar.elev_map = someFakeNum * someFakeNum .* temp_elev_map
Note that the first 2 calls of it work fine! I just commented it out so I could keep working through different errors I was having. I also change the variable names above to make it look more general!

Structs of Arrays: Type Error

I do not get the difference between the following two struct definitions. The first works without any problems, while the second gives a Type Error:
julia> struct point1
xy::Vector{Float64}
end
julia> struct point2
xy::Array{Float64,1}(2)
end
ERROR: TypeError: point2: in type definition, expected Type, got Array{Float64,1}
Stacktrace:
[1] eval(::Module, ::Any) at ./boot.jl:235
[2] eval(::Any) at ./boot.jl:234
[3] macro expansion at /Users/.julia/v0.6/Atom/src/repl.jl:186 [inlined]
[4] anonymous at ./<missing>:?
Any ideas?
The issue here is that Array{Float64,1}(2) isn't a type (i.e. typeof(Array{Float64,1}(2)) != DataType) but a newly initialized instance of a Array{Float64,1}.
If you would like to fix the dimension of the array field xy you can
1) make constructors throw errors/warnings if someone tries to initialize with an array of wrong size (this doesn't effect performance of course)
2) use StaticArrays.jl to maybe speed up your code
Pkg.add("StaticArrays")
using StaticArrays
struct point3
xy::SVector{2,Float64}
end
Test:
julia> p = point3(#SVector rand(2))
point3([0.621778, 0.083348])
julia> p = point3(rand(2))
point3([0.737558, 0.405582])
julia> p = point3(rand(3))
ERROR: Dimension mismatch. Expected input array of length 2, got length 3
Solved it:
struct point2
xy::Array{Float64,1}
end
The problem was the definition of the dimension ...

TypeError typeassert for custom typealias

I fail to understand the following behaviour
a = [1,2,3]
a::Vector # works
d = Dict(0=>a)
typealias DictVector{K,V} Dict{K, Vector{V}}
d::DictVector # fails
the error is the following
TypeError: typeassert: expected Dict{K,Array{V,1}}, got
Dict{Int64,Array{Int64,1}}
in include_string(::String, ::String) at loading.jl:441
in eval(::Module, ::Any) at boot.jl:234
in (::Atom.##65#68)() at eval.jl:40
in withpath(::Atom.##65#68, ::Void) at utils.jl:30
in withpath(::Function, ::Void) at eval.jl:46
in macro expansion at eval.jl:109 [inlined]
in (::Atom.##64#67{Dict{String,Any}})() at task.jl:60
however Vector is itself as typealias Vector{T} Array{T,1} so what is the decisive difference between the two cases?
Any clarification is highly appriciated
You're right that should work. It looks like this was a bug in the old type system in 0.5. It's fixed in the upcoming 0.6 release.
Here's a possible workaround for 0.5:
julia> typealias DictVector{K,V<:Vector} Dict{K,V}
Dict{K,V<:Array{T,1}}
julia> d::DictVector
Dict{Int64,Array{Int64,1}} with 1 entry:
0 => [1,2,3]
julia> isa(d, DictVector)
true

Resources