Julia: how to use type - julia

struct MyData
data
# constructor
function MyData()
data = 1
end
end
myData = MyData()
myData.data #error
I assumed Julia's struct was just like struct in C. So I don't know why I get an error there:
type int64 has no field data

Functions in Julia return the last expression in them. In this case, it is data = 1, that is data is returned instead of new instance of MyData. Simply add line with new(data) after data = 1 to return new instance of MyData, and it will work properly.

Normally you want to use a so-called "outer constructor", i.e. a function of the same name that is defined outside the definition of the type itself. You also want to specify the type of each field as a concrete type, e.g. Int in this example:
struct MyType
data::Int
end
This has already defined, automatically, a couple of constructors:
x = MyType(3)
x.data
You can define new outer constructors, e.g. to have a default value:
MyType() = MyType(0) # defines a new constructor
x = MyType()
The kind of constructor you were trying to define is called an "inner constructor" (since it lives inside the type definition). It is used when there is something special that you want to force for each new object. For example, you could make sure that the data must be positive and throw and error if not:
struct MyType2
data::Int
function MyType2(x::Int)
if x <= 0
throw(ArgumentError("x must be positive"))
end
new(x)
end
end
x = MyType2(3)
y = MyType2(-17)
You should have a look at the documentation on constructors:
http://docs.julialang.org/en/release-0.4/manual/constructors/

Related

Change one parameter value in structure does not affect related parameters

I have a mutable structure in Julia
#with_kw mutable struct Param
x::Float64 = 0.1
y::Float64 = 1/x
end
Now I want to change x to 0.2, so I set
para = Param() and para.x = 0.2. However, para.y does not change. But what I want is to change y automatically, is there any way in Julia to do this?
For now, Julia isn't so flexible in updating attributes based on other ones. But, gladfully, it's possible to simulate the expected behavior. For this, you need to define a custom getproperty function. Suppose I have defined a mutable composite type as follows:
julia> Base.#kwdef mutable struct Param
x::Float64=0.1
end
Param
Now I want to settle the situation to simulate the expected behavior. For this, I go for defining a custom getproperty function specifically for Param:
julia> function Base.getproperty(the_type::Param, prop::Symbol)
if prop == :y
return 1/the_type.x
end
return getfield(the_type, prop)
end
Now I create an instance of type Param holding the default value:
julia> instance = Param()
Param(0.1)
The output shows just the value of one field (x). But meanwhile, we can have the y property as we defined our custom getproperty function recently:
julia> instance.y
10.0
Now let's update the x field and observe if the y field gets updated automatically or not:
julia> instance.x = 0.2
0.2
julia> instance.y
5.0
Yes, it does!
Further setting
But still, I can't utilize the autocomplete ability of the REPL by hitting the Tab key to write instance.y. For this, I can define a custom propertynames function specifically for my composite type Param:
julia> Base.propertynames(the_type::Param) = (:x, :y)
julia> instance. #Hit Tab
x y
Now I can benefit from the autocomplete option in the REPL for y as well.
You are specifying the default value for a parameter, not an algorithmic relationship. If y is always supposed to be calculated like that and never set on it's own you can define
y(p::Param) = 1/p.x

How to hard code struct variables in Julia?

I have a Julia struct:
struct WindChillCalc
location::Tuple;
w_underground_url::String;
WindChillCalc(location, wug) = new(location, w_underground_url);
end
How do I hard code w_underground_url to contain "someString" upon the constructor of WindChillCalc being called?
Try something like below
struct testStruct
x::Real
y::String
testStruct(x,y) = new(x,"printThis")
end
test = testStruct(1,"")
test2 = testStruct(2,"")
println(test.y)
println(test2.y)
It prints "printThis" for any object.
Just write for example:
struct WindChillCalc{T}
location::T;
w_underground_url::String;
WindChillCalc(location::T) where {T <: NTuple{2, Real}} =
new{T}(location, "some string");
end
and now Julia automatically creates a concrete type for you:
julia> WindChillCalc((1, 2.5))
WindChillCalc{Tuple{Int64,Float64}}((1, 2.5), "some string")
Note that I have restricted the type of the parameter to be a two element tuple where each element is a Real. You could of course use another restriction (or use no restriction).
With this approach your code will be fast as during compile time Julia will know exact types of all fields in your struct.

Check if a type implements an interface in Julia

How to check that a type implements an interface in Julia?
For exemple iteration interface is implemented by the functions start, next, done.
I need is to have a specialization of a function depending on wether the argument type implements a given interface or not.
EDIT
Here is an example of what I would like to do.
Consider the following code:
a = [7,8,9]
f = 1.0
s = Set()
push!(s,30)
push!(s,40)
function getsummary(obj)
println("Object of type ", typeof(obj))
end
function getsummary{T<:AbstractArray}(obj::T)
println("Iterable Object starting with ", next(obj, start(obj))[1])
end
getsummary(a)
getsummary(f)
getsummary(s)
The output is:
Iterable Object starting with 7
Object of type Float64
Object of type Set{Any}
Which is what we would expect since Set is not an AbstractArray. But clearly my second method only requires the type T to implement the iteration interface.
my issue isn't only related to the iteration interface but to all interfaces defined by a set of functions.
EDIT-2
I think my question is related to
https://github.com/JuliaLang/julia/issues/5
Since we could have imagined something like T<:Iterable
Typically, this is done with traits. See Traits.jl for one implementation; a similar approach is used in Base to dispatch on Base.iteratorsize, Base.linearindexing, etc. For instance, this is how Base implements collect using the iteratorsize trait:
"""
collect(element_type, collection)
Return an `Array` with the given element type of all items in a collection or iterable.
The result has the same shape and number of dimensions as `collection`.
"""
collect{T}(::Type{T}, itr) = _collect(T, itr, iteratorsize(itr))
_collect{T}(::Type{T}, itr, isz::HasLength) = copy!(Array{T,1}(Int(length(itr)::Integer)), itr)
_collect{T}(::Type{T}, itr, isz::HasShape) = copy!(similar(Array{T}, indices(itr)), itr)
function _collect{T}(::Type{T}, itr, isz::SizeUnknown)
a = Array{T,1}(0)
for x in itr
push!(a,x)
end
return a
end
See also Mauro Werder's talk on traits.
I would define a iterability(::T) trait as follows:
immutable Iterable end
immutable NotIterable end
iterability(T) =
if method_exists(length, (T,)) || !isa(Base.iteratorsize(T), Base.HasLength)
Iterable()
else
NotIterable()
end
which seems to work:
julia> iterability(Set)
Iterable()
julia> iterability(Number)
Iterable()
julia> iterability(Symbol)
NotIterable()
you can check whether a type implements an interface via methodswith as follows:
foo(a_type::Type, an_interface::Symbol) = an_interface ∈ [i.name for i in methodswith(a_type, true)]
julia> foo(EachLine, :done)
true
but I don't quite understand the dynamic dispatch approach you mentioned in the comment, what does the generic function looks like? what's the input & output of the function? I guess you want something like this?
function foo(a_type::Type, an_interface::Symbol)
# assume bar baz are predefined
if an_interface ∈ [i.name for i in methodswith(a_type, true)]
# call function bar
else
# call function baz
end
end
or some metaprogramming stuff to generate those functions respectively at compile time?

Julia : Make method take array as parameter

I'm currently programming in Julia and I want a method (The constructor of class ProbData) to take an array of a defined type as its parameter. What I'm currently doing is:
function ProbData(variables::AbstractArray{BaseVariable, 1})
instance = new()
instance.numPara = size(variables, 1)
instance.numRand = 0
for x = variables
if x.variableType != "Det"
instance.numRand += 1
end
end
instance.getNumPara = function()
return instance.numPara
end
instance.getNumRand = function()
return instance.numRand
end
return instance
end
BaseVariable is an abstract that has three subtypes. When I try to:
x = DetVariable("test", 0.15)
P = ProbData([x])
I get this error message:
ERROR: LoadError: MethodError: 'convert' has no method matching convert(::Type{ProbData}, ::Array{DetVariable.jl,1})
How can I fix this? I've just learned this language for a few days, so if you can point out what I shouldn't have done, I would appreciate it as well.
Edit: I've found out that if I defined the parameter array of the constructor to be an array of a certain type rather than an array of an abstract, the code would work properly. However, I need the parameter to be an array, whose elements could be of any subtype of BaseVariable.
Just change the function declaration to:
function ProbData{T<:BaseVariable}(variables::AbstractArray{T, 1})

constrain argument to be in a set of values in Julia function signature

Is there a way in Julia to specify that a function argument can take one of a set of values through type annotations? For example, let's say I have function foo which accepts a single argument
function foo(x::String)
print(x)
end
the argument x can only be a String. Is there a way to further constrain it in the function signature so that it can only be for example one of the strings "right", "left", or "center"?
In Julia, the motto should be "There's a type for that!".
One way of handling this would be to create a type with a constructor that only allows the values you want (and possibly stores them in a more efficient manner).
Here is one example:
const directions = ["left", "right", "center"]
immutable MyDirection
Direction::Int8
function MyDirection(str::AbstractString)
i = findnext(directions, str, 1)
i == 0 && throw(ArgumentError("Invalid direction string"))
return new(i)
end
end
Base.show(io::IO, x::MyDirection) = print(io, string("MyDirection(\"",directions[x.Direction],"\")"))
function foo(x::MyDirection)
println(x)
end
function foo(str::AbstractString)
x = MyDirection(str)
println(x)
end
test = MyDirection("left")
foo(test)
foo("right")
Note: my example is written with Julia 0.4!
Edit:
Another approach would be to use symbols, such as :left, :right, and :center,
instead of strings.
These have the advantage of being interned (so that they can be compared simply by comparing their address), and they can also be used directly for type parameters.
For example:
immutable MyDirection{Symbol} ; end
function MyDirection(dir::Symbol)
dir in (:left, :right, :center) || error("invalid direction")
MyDirection{dir}()
end
MyDirection(dir::AbstractString) = MyDirection(symbol(dir))
That will let you do things like:
x = MyDirection("left")
which will create an immutable object of type MyDirection{:left}.
No, it is not. That would be dispatching on values, which isn't possible in Julia.
I'm not sure what your actual application is, but there are some possibly-appropriate workarounds to this, e.g.
abstract Sam81Args
type ArgRight <:Sam81Args end
type ArgLeft <:Sam81Args end
type ArgCenter <:Sam81Args end
function foo{T<:Sam81Args}(x::Type{T})
println(T)
end
foo(ArgCenter)

Resources