Dictionary in constructor for a mutable struct in Julia - julia

Is it possible to initialize a mutable struct with a variable which is a dict.I am trying the following:
mutable struct Global
speciesCnt::Int64
chromosomeCnt::Int64
nodeCnt::Int64
innov_number::Int64
innovations::Dict{(Int64,Int64),Int64}
cf::Config
function Global(cf::Config)
new(0,0,0,0,Dict{(Int64,Int64),Int64}(),cf) # global dictionary
end
end
however, when I run it I get the following error:
LoadError: TypeError: in Type, in parameter, expected Type, got Tuple{DataType,DataType}.
Any help is greatly appreciated.
I am using Julia v 1.0

A proper type signature for your dict is:
Dict{Tuple{Int64,Int64},Int64}
The easiest way to learn how type signatures in Julia look like is to create an object of the desired type and use typeof function to display its type:
julia> typeof(Dict((1,2)=>3))
Dict{Tuple{Int64,Int64},Int64}

Related

Get struct property from inside struct function errors out

Recently started to try and learn Julia through examples. I am basically trying to figure out how to access a struct property from within a function inside the struct itself. E.g:
struct Test
a::Int
foo::Function
function Test()
return new(777, xfoo)
end
function xfoo()
println(a)
end
end
t = Test()
t.foo()
I get:
ERROR: LoadError: UndefVarError: a not defined
Stacktrace:
[1] (::var"#xfoo#1")()
# Main /tmp/j.jl:10
[2] top-level scope
# /tmp/j.jl:15
in expression starting at /tmp/j.jl:15
Am I using Julia wrong or am I missing something?
Julia is not object oriented language so object oriented patterns are usually not a good idea.
Hence xfoo should be outside of Test:
function xfoo(t::Test)
println(t.a)
end
There are packages that try to emulate OOP with Julia (however this is not a Julian pattern): https://github.com/Suzhou-Tongyuan/ObjectOriented.jl
You can also easily find quite a lot of discussion behind the design decision no to make Julia OOP. Start with: https://discourse.julialang.org/t/why-there-is-no-oop-object-oriented-programming-in-julia/86723
Workaround
Just out of curiosity one can find some workaround to attach a function to a struct (not a recommended design pattern!). For an example:
mutable struct MyTest
a::Int
foo::Function
function MyTest()
s = Ref{MyTest}()
s[] = new(777, () -> println(s[].a))
s[]
end
end
And some sample usage:
julia> t = MyTest();
julia> t.foo()
777
julia> t.a = 900;
julia> t.foo()
900

Can you create a singleton in Julia?

I know that Julia does not have OOP but that multiple dispatch enables similar ideas. Given how seemingly contentious the use of singletons are in Python, I am wondering if there is a similar idea Julia (i.e. a struct that can only be instantiated once).
I am wondering if there's a way to have the constructor keep track of the number of times an object was instantiated with a global var or something like that? Or it's altogether not be possible?
The main way people make singletons in Julia is to define an empty struct (which means that it has 0 size), and define methods that return information for it.
struct Singleton
end
data(::Singleton) = "whatever you want it to do"
etc.
From this book, a singleton can be defined as a type without fields:
struct MySingleton end
julia> MySingleton() === MySingleton()
true
You can also use Val, which can receive any value (of bit type):
julia> Val(1) === Val(1)
true
julia> Val(:foo) === Val(:foo)
true
using Val you can write something like this:
julia> do_something(::Val{:asymbol}) = println("foo")
julia> do_something(::Val{:anothersymbol}) = println("bar")
julia> do_something(s::String) = do_something(Val{Symbol(s)})
julia> do_something("asymbol")
foo
The definition of Val is:
struct Val{x} end
So, for a more clear readability of your code, you could define your own singleton type as, for example:
struct Command{x} end

How to define a constant in Julia struct

I want to define a struct:
struct unit_SI_gen
x::Float32
const c = 2.99792458e8
speed(x)=c*x
end
However, it raise an error :
syntax: "c = 2.99792e+08" inside type definition is reserved
I know I cant use struct as class in python, but I can not find how to solve this problem.
How to define a constant in struct ?
Given I agree with what was said above about normal usage of struct in Julia, it is actually possible to define what was requested in the question using an inner constructor:
struct unit_SI_gen{F} # need a parametric type to make it fast
x::Float32
c::Float64 # it is a constant across all unit_SI_gen instances
speed::F # it is a function
function unit_SI_gen(x)
c = 2.99792458e8
si(x) = c*x
new{typeof(si)}(x, c, si)
end
end
I second #Tasos's comment, you should probably make yourself familiar with Julia's structs first. The relevant part of the documentation is probably here.
Since you declared your struct as struct (in contrast to mutable struct) it is immutable and hence all (immutable) fields of the struct are constants in the sense that they can't be changed.
julia> struct A
x::Int
end
julia> a = A(3)
A(3)
julia> a.x = 4
ERROR: type A is immutable
Stacktrace:
[1] setproperty!(::A, ::Symbol, ::Int64) at .\sysimg.jl:19
[2] top-level scope at none:0
Note, that they get their unchangeable value in the construction process and not in the struct definition.
Also, methods should generally live outside of the struct definition.

How to get a slice of references from a vector in Rust?

Somewhere in the API I use I have a function which takes &[&A] as argument but I only have a vector of A objects. When I try to use this function with
following syntax
pub struct A(pub u64);
fn test(a: &[&A]){}
fn main() {
let v = vec![A(1), A(2), A(3)];
let a = &v[..];
test(a);
}
I have a error:
<anon>:12:9: 12:10 error: mismatched types:
expected `&[&A]`,
found `&[A]`
(expected &-ptr,
found struct `A`) [E0308]
I have made some attempts but without any success:
let a = &v[&..]
and
let a = &v[&A]
How can I make &[&A] from Vec<A>?
Short answer: you can't. These types are not compatible with each other.
What you could do if this is really what the API needs is
test(&v.iter().collect::<Vec<_>>());
But this allocates a new vector. If you are the author of the API, consider changing it: &[&T] is a weird type to work with since you need different owners for the slice and the objects in it. &[T] already has a pass-by-reference semantic of the inner objects.

Can I build a parameterless constructor for a parametric type in an outer constructor?

In order to instantiate a type like x = MyType{Int}()
I can define a inner constructor.
immutable MyType{T}
x::Vector{T}
MyType() = new(T[])
end
Is it possible to achieve the same objective using an outer constructor?
This can be done using the following syntax:
(::Type{MyType{T}}){T}() = MyType{T}(T[])
The thing in the first set of parentheses describes the called object. ::T means "of type T", so this is a definition for calling an object of type Type{MyType{T}}, which means the object MyType{T} itself. Next {T} means that T is a parameter of this definition, and a value for it must be available in order to call this definition. So MyType{Int} matches, but MyType doesn't. From there on, the syntax should be familiar.
This syntax is definitely a bit fiddly and unintuitive, and we hope to improve it in a future version of the language, hopefully v0.6.
I may be wrong, but if you cannot build parameterless function like this:
julia> f{T}() = show(T)
WARNING: static parameter T does not occur in signature for f at none:1.
The method will not be callable.
f (generic function with 1 method)
therefore you won't be able to do this:
julia> immutable MyType{T}
x::Vector{T}
end
julia> MyType{T}() = MyType{T}(T[])
WARNING: static parameter T does not occur in signature for call at none:1.
The method will not be callable.
MyType{T}
julia> x = MyType{Int}()
ERROR: MethodError: `convert` has no method matching convert(::Type{MyType{Int64}})
...
Every outer constructor is also a function.
You can say
f(T::Type) = show(T)
and also
MyType(T::Type) = MyType(T[])
But julia needs to see the type in the call to know which you want.

Resources