Is there any function such as repmat for struct in julia? - julia

would you please help me. I want to produce a population of struct in Julia.In matalab,we can use repmat for a structure. but in Julia it is impossible. is there any function like repmat in Julia?
for example:
npop=20;
struct individual
position
cost
end
individual1=individual([],[])
repmat(individual1,npop,1)
repeat(individual1,npop,1)
repmat(individual1,npop,1)
ERROR: MethodError: no method matching repmat(::individual, ::Int64, ::Int64)
Closest candidates are:
repmat(::Union{AbstractArray{T,1}, AbstractArray{T,2}} where T, ::Int64, ::Int64) at abstractarray
math.jl:311
repmat(::Union{AbstractArray{T,1}, AbstractArray{T,2}} where T, ::Integer, ::Integer) at abstracta
rraymath.jl:334
repmat(::AbstractArray{T,1} where T, ::Int64) at abstractarraymath.jl:325
...
Stacktrace:
[1] macro expansion at C:\Users\admin\AppData\Local\JuliaPro-0.6.4.1\pkgs-0.6.4.1\v0.6\Atom\src\rep
l.jl:118 [inlined]
[2] anonymous at .\<missing>:?
julia>
julia> repmat(individual1,npop,1)
ERROR: MethodError: no method matching repmat(::individual, ::Int64, ::Int64)
Closest candidates are:
repmat(::Union{AbstractArray{T,1}, AbstractArray{T,2}} where T, ::Int64, ::Int64) at abstractarray
math.jl:311
repmat(::Union{AbstractArray{T,1}, AbstractArray{T,2}} where T, ::Integer, ::Integer) at abstracta
rraymath.jl:334
repmat(::AbstractArray{T,1} where T, ::Int64) at abstractarraymath.jl:325
...
Stacktrace:
[1] macro expansion at C:\Users\admin\AppData\Local\JuliaPro-0.6.4.1\pkgs-0.6.4.1\v0.6\Atom\src\rep
l.jl:118 [inlined]
[2] anonymous at .\<missing>:?
if loop is used it is possible
pop=individual([],[])
for i=2:npop
pop=[pop;individual1]
end
and
julia> pop
20-element Array{individual,1}:
individual(Any[], Any[])
individual(Any[], Any[])
individual(Any[], Any[])
individual(Any[], Any[])
individual(Any[], Any[])
individual(Any[], Any[])
individual(Any[], Any[])
individual(Any[], Any[])
individual(Any[], Any[])
individual(Any[], Any[])
individual(Any[], Any[])
individual(Any[], Any[])
individual(Any[], Any[])
individual(Any[], Any[])
individual(Any[], Any[])
individual(Any[], Any[])
individual(Any[], Any[])
individual(Any[], Any[])
individual(Any[], Any[])
individual(Any[], Any[])
but I couldn't find a function like repmat in Julia.

If I understand what you want to achieve correctly (assuming you want to do a kind of ABM) this is the way to do it:
[individual([],[]) for i in 1:npop]
In this way every individual will be allocated separately (and this is probably what you want).
As a side note it would be better to add types to position and cost for performance reasons. Here is an example assuming that position will be a vector of two element tuples containing a position and cost is a vector of floats:
struct individual
position::Vector{Tuple{Float64,Float64}}
cost::Vector{Float64}
end
And then you should write:
[individual(Tuple{Float64,Float64}[],Float64[]) for i in 1:npop]
EDIT
Note that struct in Julia is not mutable. This means that you cannot rebind the values that position and cost point to. Therefore you have two options.
Option 1. Define a struct as mutable like this:
mutable struct individual
position
cost
end
and then the code you have written will work.
Option 2 Update without rebinding
update a vector in a struct that is not mutable without rebinding it. E.g. (using your original definitions)
pop = [individual([],[]) for i in 1:npop]
for i=1:npop
append!(pop[i].position, rand(0:1,10))
end
or simply initialize it as needed:
pop = [individual(rand(0:1,10),[]) for i in 1:npop]
As an additional comment please note that in Julia you generally do not need to make an adjoint as you did in (rand(0:1,10))'. Operating on vectors typically good enough. And in Option 2 (normal struct you would not be able to append 2-dimensional object to [] which is 1-dimensional).

Related

Iterate over the types in a Tuple DataType

Is there a way to iterate over the types contained in a Tuple{...} DataType? For instance, if I have the type Tuple{String, Int}, I'd like to be able to use something like values(Tuple{String, Int}) to return an iterator of String and Int, like this:
julia> collect(values(Tuple{String, Int}))
2-element Array{DataType,1}:
String
Int64
But of course that doesn't actually work:
julia> values(Tuple{String, Int})
Tuple{String,Int64}
julia> collect(values(Tuple{String, Int}))
ERROR: MethodError: no method matching length(::Type{Tuple{String,Int64}})
Closest candidates are:
length(::Core.SimpleVector) at essentials.jl:596
length(::Base.MethodList) at reflection.jl:852
length(::Core.MethodTable) at reflection.jl:938
...
Stacktrace:
[1] _similar_for(::UnitRange{Int64}, ::Type{Any}, ::Type{T} where T, ::Base.HasLength) at ./array.jl:576
[2] _collect(::UnitRange{Int64}, ::Type{T} where T, ::Base.HasEltype, ::Base.HasLength) at ./array.jl:609
[3] collect(::Type{T} where T) at ./array.jl:603
[4] top-level scope at REPL[30]:1
I would prefer a solution that does not involve digging into the internals of DataType.
A tuple type is only a DataType. Everything operating on it will have to involve DataTypes -- you're looking for a function of type DataType -> [DataType]. One possible answer is Tuple{String, Int}.parameters. At least in 1.3, Core.Compiler also contains
datatype_fieldtypes(x::DataType) = ccall(:jl_get_fieldtypes, Any, (Any,), x)
which only internal and undocumented, though. Both result in a Core.SimpleVector.
But then I remembered that tuple parts can be treated both as indices and as fields. So it turns out fieldtypes would probably be your favourite:
julia> fieldtypes(Tuple{Int, String})
(Int64, String)
The other methods, however, have the advantage that you can use them with any parametrized type. This often comes in handy in generated functions.

Parametric composite type inner constructors in Julia: Why is `where {T}` necessary?

Why does this raise LoadError: UndefVarError: T not defined:
struct Point{T}
x::T
y::T
Point{T}(x,y) = new(x,y)
end
while this works fine:
struct Point{T}
x::T
y::T
Point{T}(x,y) where {T} = new(x,y)
end
?
It seems that once upon a time they were both fine: Inner constructor of parametric type
EDIT: To clarify, I would have expected the fact that we are within the struct Point{T} block to have made it clear what T refers to even in the first case.
Without where clause T is inherited from the global scope (which is kind of surprising, but this is how it works):
julia> T = String
String
julia> struct Point{T}
x::T
y::T
Point{T}(x,y) = new(x,y)
end
julia> Point{String}("b","a")
Point{String}("b", "a")
julia> Point{String}(SubString("b",1,1),SubString("a",1,1))
Point{String}("b", "a")
julia> Point{Int}(1, 2)
ERROR: MethodError: no method matching Point{Int64}(::Int64, ::Int64)
julia> Point{String}(1, 2)
ERROR: MethodError: Cannot `convert` an object of type Int64 to an object of type String
EDIT
The short answer, given the comments on Discourse, is that the reason for this is that T of struct is not known at the moment an inner constructor is called.

Julia: what does the "<:" symbol mean?

What does this mean in function signatures, for example:
convert(::Type{T}, z::Complex) where {T<:Real}
Strictly speaking, one should differentiate between the predicate Base.:(<:), as described in #Saqib's answer, and the syntactic usage of <: for describing constraints.
This syntactic usage can occur in type parameter declarations of methods, to constrain a type variable to be a subtype of some other type:
f(x::T) where {T<:Real} = zero(x)
A sort of special case of this is when you constrain the type parameter of a struct (struct Foo{T<:Real} ... end) -- that constrains the methods of the generated constructor, and allows the type constructor to be applied only to the constrained subtypes.
On the other hand, outside of type parameters, <: can be used to declare a new type as a subtype of some other (necessarily abstract) type:
struct Foo <: Real end
Although both cases are in line with the meaning of the subtyping predicate, you can't replace them with other arbitrary expressions (e.g., you can't write ... where {isreal(T)} in f).
<:(T1, T2)
Subtype operator: returns true if and only if all values of type T1 are
also of type T2.
Examples:
Float64 <: AbstractFloat
=> true
Vector{Int} <: AbstractArray
=> true
Matrix{Float64} <: Matrix{AbstractFloat}
=> false

How to define a parametric type over parametric type?

Suppose I have types
immutable X{T}
a::T
end
immutable Y{T}
a::T
end
I would like to do something like
type A{T, U}
x::U{T}
y::T
end
So that the instances could be A(X(a), a) or A(Y(a), a)
It doesn't work as
LoadError: TypeError: Type{...} expression: expected Type{T}, got TypeVar
What's the correct way for it?
As the error says, U is a TypeVar, not a Type. The answer is to make U a real type:
julia> abstract U{T}
julia> immutable X{T} <: U{T}
a::T
end
julia> immutable Y{T} <: U{T}
a::T
end
julia> type A{T}
x::U{T}
y::T
end
julia> A(X(1),1)
A{Int64}(X{Int64}(1),1)
julia> A(X(1),1.)
ERROR: MethodError: no method matching A{T}(::X{Int64}, ::Float64)
Closest candidates are:
A{T}{T}(::U{T}, ::T) at REPL[4]:2
A{T}{T}(::Any) at sysimg.jl:53
julia> A(Y(1),1)
A{Int64}(Y{Int64}(1),1)

Pair Varargs input with one element of fixed type

I can construct the following:
foo(p::Pair...) = dostuff
This will work for a list of pairs. I would like to do the following:
foo{N}(p::Pair{Symbol,N}...) = dostuff
where the first entry of each pair is a Symbol, but the second entry is unconstrained. The construction above requires that all 2nd entries are of the same type, but I want to allow any 2nd entry:
foo(:a=>1, :b=>"hi")
Is there a way to do this?
Do I need to just go with the first version and enforce the argument type in the function itself and throw an error?
Since parametric types with unspecified trailing type parameters are treated as abstract supertypes, matching the specified types, the type Pair{Symbol} matches any pair with first parameter being Symbol with any second parameter. Thus, you can write the method signature you want like this way:
foo(p::Pair{Symbol}...) = "pairs from symbols"
This doesn't help if you want to dispatch on the second type parameter but not the first. To accomplish that, you need a type alias:
typealias Riap{B,A} Pair{A,B}
foo(p::Riap{Symbol}...) = "pairs to symbols"
We can see these two methods in action:
julia> foo(:a => 1.5, :b => "x")
"pairs from symbols"
julia> foo(1.5 => :a, "x" => :b)
"pairs to symbols"
julia> foo(:a => :b, :c => :d)
ERROR: MethodError: foo(::Pair{Symbol,Symbol}, ::Pair{Symbol,Symbol}) is ambiguous. Candidates:
foo(p::Pair{A<:Any,Symbol}...) at REPL[5]:1
foo(p::Pair{Symbol,B<:Any}...) at REPL[1]:1
in eval(::Module, ::Any) at ./boot.jl:231
in macro expansion at ./REPL.jl:92 [inlined]
in (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at ./event.jl:46
julia> foo()
ERROR: MethodError: foo( is ambiguous. Candidates:
foo(p::Pair{A<:Any,Symbol}...) at REPL[5]:1
foo(p::Pair{Symbol,B<:Any}...) at REPL[1]:1
in eval(::Module, ::Any) at ./boot.jl:231
in macro expansion at ./REPL.jl:92 [inlined]
in (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at ./event.jl:46

Resources