I want to create a structure in Julia which contains two floating point variables (coorx, velx) and one vector array of two elements which contains gradients with two elements, my idea is as follows:
struct part_struct
coorx::Float64
velx::Float64
gradx::Vector{Float64}(undef,2)
end
However, when I try to create an array of 10 of such structures:
num = 10
part = Array{part_struct,1}(undef, num)
I get the error:
TypeError: in part_struct, in type definition, expected Type, got a value of type Array{Float64,1}
How could I create such a structure in Julia?
you should put the type of the array in the struct, like that:
struct PartStruct
coorx::Float64
velx::Float64
gradx::Vector{Float64}
end
Note that you can't restrict the size of a Vector in a struct. To do so, you can use a Tuple instead (it should also have better performance):
struct PartStruct
coorx::Float64
velx::Float64
gradx::NTuple{2, Float64} # (equivalent to Tuple{Float64, Float64})
end
This is an immutable struct, which might not be what you want
Related
I want to append an index to an Integer array during a loop. Like add 3 to [1,2] and get an array like [1,2,3]. I don't know how to write it in the format and I cannot get the answer on the Internet.
You can use Vectors to do the something similar using the & operator. You can access the individual elements just like an array, though you use () instead of []. Or you can just use a for loop and get the element directly.
See the below example:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Vectors;
procedure jdoodle is
-- Create the package for a vector of integers
package Integer_Vectors is new Ada.Containers.Vectors(Positive,Integer);
-- Using subtype to make just the Vector type visible
subtype Vector is Integer_Vectors.Vector;
-- Make all the primitive operations of Vector visible
use all type Vector;
-- Create a variable
V : Vector;
begin
-- Add an element to the vector in each iteration
for i in 1..10 loop
V := V & i;
end loop;
-- Show the results
for Element of V loop
Put_Line(Element'Image);
end loop;
-- Print the 2nd element of the array
Put_Line(Integer'Image(V(2)));
end jdoodle;
Ada arrays are first class types, even when the array type is anonymous. Thus a 2-dimensional array is a different type than a 3-dimensional array. Furthermore, arrays are not defined by directly specifying the number of elements in a dimension as they are in languages derived from C.
For instance, if you define a 2-dimensional array such as
type array_2d is array (Integer range 0..1, Integer range 1..2);
You have defined an array with a first range of 0..1 and a second range of 1..2. This would be a square matrix containing 4 elements.
You cannot simply add another dimension to an object of the type array_2d described above. Such an array must be of a different type.
Furthermore, one cannot change the definition of an array object after it is created.
Ok, so while this is a simple question it gets into the interesting details of design very quickly. The first thing is that an array "always knows its bounds" -- this language design element impacts the usage of the language profoundly: instead of having to pass the length of the array as a parameter, and possibly going out-of-sync, like in C you simply pass the array and let the "it knows its bounds" take care of the management.
Second, the Array is always static-length, meaning it cannot be changed once created. Caveat: Creating an array can be done in a "dynamic" setting, like querying user-input.
Third, if the subtype is unconstrained than it can have "variable" length. -- This means that you can have something like Type Integer_Vector is Array(Positive Range <>) of Integer and have parameters that operate on any size value passed in (and return-values that can be any size). This, in turn, means that your handling of such subtypes tends itself toward the more general.
Fourth, all of these apply and combine so that a lot of the 'need' for dynamically sized arrays aren't needed -- yes, there are cases where it is needed, or where it is more convenient to have a single adjustable object; this is what Ada.Containers.Vectors addresses -- but in the absence of needing a truly dynamically-sizing object you can use processing for achieving your goals.
Consider the following example:
Type Integer_Vector is Array(Positive range <>) of Integer;
Function Append( Input : Integer_Vector; Element : Integer ) return Integer_Vector is
( Input & Element );
X : Constant Integer_Vector:= (1,2);
Y : Integer_Vector renames Append(X, 3);
These three design choices combine to allow some intere
I am trying to define a dictionary that takes strings as keys and any values. Thus, I try to use Dict{String, <:Any} as type. However, the return value to that expression is
> Dict{String,#s27} where #s27
Moreover, if I try to define a dictionary of that type I get an error:
For Dict{String,<:Any}() I get ERROR: MethodError: no method matching Dict{String,#s28} where #s28()
For Dict{String,<:Any}("aa"=>42) I get ERROR: MethodError: no method matching Dict{String,#s29} where #s29(::Pair{String,Int64})
I also tried using Dict{String} (which should be equivalent), with similar results.
What am I missing about types of dictionaries here?
What you are looking for is a Dict{String, Any}, not Dict{String, <:Any}. The first one is a concrete type, namely a dict that takes strings as keys and anything as values. The second, Dict{String, <:Any} is not actually a concrete type, but a unionall type. That means it is an infinite set of types. And the error you are seeing is that you can't instantiate this set of types. You can only instantiate a concrete (leaf) type.
Another way of writing Dict{String, <:Any} is Dict{String, T} where T <: Any, and that makes it a little clearer what it is. It is the set of all types of Dict that has String as they key type and a type that is a subtype of Any as their value type.
So for example we can say that Dict{String, Int} is a subtype of the infinite set Dict{String, <:Any}.
Edit: One use of unionall types is to be able to restrict the kind of type you take to fine grained level. For example, a counting function may look like this:
function count_stuff(stuff, counter::Dict{T, <:Integer}) where T
# stuff here¨
end
The second argument here is a Dict that has some subtype of Integer as a value type and any type as a key type. That's basically what you'd need to use the dict as a counter.
If I want to specify that my function returns a Bool I do:
function myfunc(a,b)::Bool
What if I want to specify that I will return a vector of 4 Int32 elements?
a = Vector{Int32}(undef, 4)
You can't, and you don't have to.
The return type annotation is to declare the return type.
The length of a Vector is not part of its type.
it is part of its value, and it can change. (e.g. push! can be called on it).
Notice:
julia> typeof([1,2,3,4])
Array{Int64,1}
(Vector{T} is just a constant for Array{T,1})
So all you would do is delcare the type:
function myfunc(a,b)::Vector{Int}
Alternatively, you might want a NTuple{Int,4} i.e. a Tuple{Int, Int, Int, Int},
or a SVector{Int,4} from StaticArrays.jl
In general return type annotation is not super useful.
It basically boils down to the code automatically calling convert{RETURNTYPE, raw_return_value), which may error.
This can be helpful on occation for making your code type-stable, if you lose track of what types different are being returned from different return points (if you have multiple).
Rarely it might help the compiler type-infer. (Since convert always returns the indictated target type).
Some argue this serves a documentation purpose also.
I would like to check if a variable is scalar in julia, such as Integer, String, Number, but not AstractArray, Tuple, type, struct, etc. Is there a simple method to do this (i.e. isscalar(x))
The notion of what is, or is not a scalar is under-defined without more context.
Mathematically, a scalar is defined; (Wikipedia)
A scalar is an element of a field which is used to define a vector space.
That is to say, you need to define a vector space, based on a field, before you can determine if something is, or is not a scalar (relative to that vector space.).
For the right vector space, tuples could be a scalar.
Of-course we are not looking for a mathematically rigorous definition.
Just a pragmatic one.
Base it off what Broadcasting considers to be scalar
I suggest that the only meaningful way in which a scalar can be defined in julia, is of the behavior of broadcast.
As of Julia 1:
using Base.Broadcast
isscalar(x::T) where T = isscalar(T)
isscalar(::Type{T}) where T = BroadcastStyle(T) isa Broadcast.DefaultArrayStyle{0}
See the docs for Broadcast.
In julia 0.7, Scalar is the default. So it is basically anything that doesn't have specific broadcasting behavior, i.e. it knocks out things like array and tuples etc.:
using Base.Broadcast
isscalar(x::T) where T = isscalar(T)
isscalar(::Type{T}) where T = BroadcastStyle(T) isa Broadcast.Scalar
In julia 0.6 this is a bit more messy, but similar:
isscalar(x::T) where T = isscalar(T)
isscalar(::Type{T}) where T = Base.Broadcast._containertype(T)===Any
The advantage of using the methods for Broadcast to determine if something is scalar, over using your own methods, is that anyone making a new type that is going to act in a scalar way must make sure it works with those methods correctly
(or actually nonscalar since scalar is the default.)
Structs are not not scalar
That is to say: sometimes structs are scalar and sometimes they are not and it depends on the struct.
Note however that these methods do not consider struct to be non-scalar.
I think you are mistaken in your desire to.
Julia structs are not (necessarily or usually) a collection type.
Consider that: BigInteger, BigFloat, Complex128 etc etc
are all defined using structs
I was tempted to say that having a start method makes a type nonscalar, but that would be incorrect as start(::Number) is defined.
(This has been debated a few times)
For completeness, I am copying Tasos Papastylianou's answer from the comments to here. If all you want to do is distinguish scalars from arrays you can use:
isa(x, Number)
This will output true if x is a Number (like a float or an int), and output false if x is an Array (vector, matrix, etc.)
I found myself needing to capture the notion of if something was scalar or not recently in MultiResolutionIterators.jl.
I found the boardcasting based rules from the other answer,
did not meet my needs.
In particular I wanted to consider strings as nonscalar.
I defined a trait,
bases on method_exists(start, (T,)),
with some exceptions as mentioned e.g. for Number.
abstract type Scalarness end
struct Scalar <: Scalarness end
struct NotScalar <: Scalarness end
isscalar(::Type{Any}) = NotScalar() # if we don't know the type we can't really know if scalar or not
isscalar(::Type{<:AbstractString}) = NotScalar() # We consider strings to be nonscalar
isscalar(::Type{<:Number}) = Scalar() # We consider Numbers to be scalar
isscalar(::Type{Char}) = Scalar() # We consider Sharacter to be scalar
isscalar(::Type{T}) where T = method_exists(start, (T,)) ? NotScalar() : Scalar()
Something similar is also done by AbstractTrees.jl
isscalar(x) == applicable(start, x) && !isa(x, Integer) && !isa(x, Char) && !isa(x, Task)
I would like to use a subtype of a function parameter in my function definition. Is this possible? For example, I would like to write something like:
g{T1, T2<:T1}(x::T1, y::T2) = x + y
So that g will be defined for any x::T1 and any y that is a subtype of T1. Obviously, if I knew, for example, that T1 would always be Number, then I could write g{T<:Number}(x::Number, y::T) = x + y and this would work fine. But this question is for cases where T1 is not known until run-time.
Read on if you're wondering why I would want to do this:
A full description of what I'm trying to do would be a bit cumbersome, but what follows is a simplified example.
I have a parameterised type, and a simple method defined over that type:
type MyVectorType{T}
x::Vector{T}
end
f1!{T}(m::MyVectorType{T}, xNew::T) = (m.x[1] = xNew)
I also have another type, with an abstract super-type defined as follows
abstract MyAbstract
type MyType <: MyAbstract ; end
I create an instance of MyVectorType with vector element type set to MyAbstract using:
m1 = MyVectorType(Array(MyAbstract, 1))
I now want to place an instance of MyType in MyVectorType. I can do this, since MyType <: MyAbstract. However, I can't do this with f1!, since the function definition means that xNew must be of type T, and T will be MyAbstract, not MyType.
The two solutions I can think of to this problem are:
f2!(m::MyVectorType, xNew) = (m.x[1] = xNew)
f3!{T1, T2}(m::MyVectorType{T1}, xNew::T2) = T2 <: T1 ? (m.x[1] = xNew) : error("Oh dear!")
The first is essentially a duck-typing solution. The second performs the appropriate error check in the first step.
Which is preferred? Or is there a third, better solution I am not aware of?
The ability to define a function g{T, S<:T}(::Vector{T}, ::S) has been referred to as "triangular dispatch" as an analogy to diagonal dispatch: f{T}(::Vector{T}, ::T). (Imagine a table with a type hierarchy labelling the rows and columns, arranged such that the super types are to the top and left. The rows represent the element type of the first argument, and the columns the type of the second. Diagonal dispatch will only match the cells along the diagonal of the table, whereas triangular dispatch matches the diagonal and everything below it, forming a triangle.)
This simply isn't implemented yet. It's a complicated problem, especially once you start considering the scoping of T and S outside of function definitions and in the context of invariance. See issue #3766 and #6984 for more details.
So, practically, in this case, I think duck-typing is just fine. You're relying upon the implementation of myVectorType to do the error checking when it assigns its elements, which it should be doing in any case.
The solution in base julia for setting elements of an array is something like this:
f!{T}(A::Vector{T}, x::T) = (A[1] = x)
f!{T}(A::Vector{T}, x) = f!(A, convert(T, x))
Note that it doesn't worry about the type hierarchy or the subtype "triangle." It just tries to convert x to T… which is a no-op if x::S, S<:T. And convert will throw an error if it cannot do the conversion or doesn't know how.
UPDATE: This is now implemented on the latest development version (0.6-dev)! In this case I think I'd still recommend using convert like I originally answered, but you can now define restrictions within the static method parameters in a left-to-right manner.
julia> f!{T1, T2<:T1}(A::Vector{T1}, x::T2) = "success!"
julia> f!(Any[1,2,3], 4.)
"success!"
julia> f!(Integer[1,2,3], 4.)
ERROR: MethodError: no method matching f!(::Array{Integer,1}, ::Float64)
Closest candidates are:
f!{T1,T2<:T1}(::Array{T1,1}, ::T2<:T1) at REPL[1]:1
julia> f!([1.,2.,3.], 4.)
"success!"