Let's say I have an NTuple with 4 entries of Int64 uninitiallized. How do I set the value of each index separately?
I tried the setindex function of base but it didn't work. Any idea?
T = NTuple{4,Int64}
setindex(T,9,2) # set T(2) to 9
You probably meant NTuple{4, Int64} not Ntuple{4, Int64}.
NTuple is a compact way of representing the type tuples having elements of a single type (not actual values but their types; the thing that might be confusing here is that NTuple{4, Int64} is also technically a value that you can bind to a variable, but this is not what you probably want to do given your question).
You can check this by looking up help on it. In your case it represents a type for a tuple of length 4 and all elements of type Int64. For example (1,2,3,4) is such a tuple. You can check it by writing (1,2,3,4) isa NTuple{4, Int64} which will evaluate to true.
Now if you ask why a tuple like (1,2,3,4) does not support setindex! the reason is that tuples are immutable in Julia, see https://docs.julialang.org/en/latest/manual/types/#Tuple-Types-1. This means that you have to assign a value to each field of a tuple upon its construction and it cannot be mutated.
If you want a mutable container you should probably consider using a vector instead of a tuple. For example:
julia> x = Vector{Int}(undef, 4)
4-element Array{Int64,1}:
0
0
0
0
julia> x[2] = 9
9
julia> x
4-element Array{Int64,1}:
0
9
0
0
Related
Is there a difference between Array and Vector?
typeof(Array([1,2,3]))
Vector{Int64}
typeof(Vector([1,2,3]))
Vector{Int64}
Both seem to create the same thing, but they are not the same:
Array == Vector
false
Array === Vector
false
So, what is actually the difference?
The difference is that Vector is a 1-dimensional Array, so when you write e.g. Vector{Int} it is a shorthand to Array{Int, 1}:
julia> Vector{Int}
Array{Int64,1}
When you call constructors Array([1,2,3]) and Vector([1,2,3]) they internally get translated to the same call Array{Int,1}([1,2,3]) as you passed a vector to them.
You would see the difference if you wanted to pass an array that is not 1-dimensional:
julia> Array(ones(2,2))
2×2 Array{Float64,2}:
1.0 1.0
1.0 1.0
julia> Vector(ones(2,2))
ERROR: MethodError: no method matching Array{T,1} where T(::Array{Float64,2})
Also note the effect of:
julia> x=[1,2,3]
3-element Array{Int64,1}:
1
2
3
julia> Vector(x)
3-element Array{Int64,1}:
1
2
3
julia> Vector(x) === x
false
So essentially the call Vector(x) makes a copy of x. Usually in the code you would probably simply write copy(x).
A general rule is that Array is a parametric type that has two parameters given in curly braces:
the first one is element type (you can access it using eltype)
the second one is the dimension of the array (you can access it using ndims)
See https://docs.julialang.org/en/v1/manual/arrays/ for details.
Vector is an alias for a one-dimensional Array. You can see that in the Julia REPL:
julia> Vector
Array{T, 1} where T
julia> Vector{Int32}
Array{Int32, 1}
Similarly, a Matrix is a 2-dimensional Array:
julia> Matrix
Array{T,2} where T
I'm trying to write a Julia function, which can accept both 1-dimensional Int64 and Float64 array as input argument. How can I do this without defining two versions, one for Int64 and another for Float64?
I have tried using Array{Real,1} as input argument type. However, since Array{Int64,1} is not a subtype of Array{Real,1}, this cannot work.
A genuine, non secure way to do it is, with an example:
function square(x)
# The point is for element-wise operation
out = x.*x
end
Output:
julia> square(2)
4
julia> square([2 2 2])
1×3 Array{Int64,2}:
4 4 4
In Matlab I can write:
[0:n]
to get an array (1,n). For n=2, I get:
0 1 2
How to do the same in Julia? The purpose is to get the same type of array (1,3).
I know I can write [0 1 2], but I want something general like in Matlab.
In julia, the colon operator (in this context, anyway) returns a UnitRange object. This is an iterable object; that means you can use it with a for loop, or you can collect all its contents, etc. If you collect its contents, what you get here is a Vector.
If what you're after is explicitly a RowVector, then you can collect the contents of the UnitRange, and reshape the resulting vector accordingly (which in this case can be done via a simple transpose operation).
julia> collect(1:3).'
1×3 RowVector{Int64,Array{Int64,1}}:
1 2 3
The .' transpose operator is also defined for UnitRange arguments:
julia> (1:3).'
1×3 RowVector{Int64,UnitRange{Int64}}:
1 2 3
However, note the difference in the resulting type; if you apply .' again, you get a UnitRange object back again.
If you don't particularly like having a "RowVector" object, and want a straightforward array, use that in an Array constructor:
julia> Array((1:3).')
1×3 Array{Int64,2}:
1 2 3
(above as of latest julia 0.7 dev version)
I have an array of type Array{Float64,2} but it's an array of 1 column, and I'm unable to pass this into a function that's expecting a single-column array of type Array{Float64,1}. I don't really understand what the 2 means or how to fix my problem, and I haven't been able to figure it out by searching through any documentation.
In Array{Float64,2}, the 2 is the number of dimensions in the array. Since you say it's "it's an array of 1 column", you probably have something which is 2-dimensional with either one row or one column, i.e. one of
julia> c = rand(1,3)
1x3 Array{Float64,2}:
0.190944 0.928697 0.251519
julia> d = rand(3,1)
3x1 Array{Float64,2}:
0.0818493
0.0342291
0.58341
To turn this into a 1-dimensional array, you could slice the array manually or use squeeze, as you prefer:
julia> c[1,:]
3-element Array{Float64,1}:
0.190944
0.928697
0.251519
julia> squeeze(d,2)
3-element Array{Float64,1}:
0.0818493
0.0342291
0.58341
Either approach should give you something of type Array{Float64,1}.
As noted in the comments, another approach is to use reshape, e.g. (using a different random c):
julia> reshape(c, length(c))
3-element Array{Float64,1}:
0.680653
0.0573147
0.607054
This has the advantage -- and disadvantage -- of not caring whether you have an array of shape 1xN or Nx1.
I was delighted to learn that Julia allows a beautifully succinct way to form inner products:
julia> x = [1;0]; y = [0;1];
julia> x'y
1-element Array{Int64,1}:
0
This alternative to dot(x,y) is nice, but it can lead to surprises:
julia> #printf "Inner product = %f\n" x'y
Inner product = ERROR: type: non-boolean (Array{Bool,1}) used in boolean context
julia> #printf "Inner product = %f\n" dot(x,y)
Inner product = 0.000000
So while i'd like to write x'y, it seems best to avoid it, since otherwise I need to be conscious of pitfalls related to scalars versus 1-by-1 matrices.
But I'm new to Julia, and probably I'm not thinking in the right way. Do others use this succinct alternative to dot, and if so, when is it safe to do so?
There is a conceptual problem here. When you do
julia> x = [1;0]; y = [0;1];
julia> x'y
0
That is actually turned into a matrix * vector product with dimensions of 2x1 and 1 respectively, resulting in a 1x1 matrix. Other languages, such as MATLAB, don't distinguish between a 1x1 matrix and a scalar quantity, but Julia does for a variety of reasons. It is thus never safe to use it as alternative to the "true" inner product function dot, which is defined to return a scalar output.
Now, if you aren't a fan of the dots, you can consider sum(x.*y) of sum(x'y). Also keep in mind that column and row vectors are different: in fact, there is no such thing as a row vector in Julia, more that there is a 1xN matrix. So you get things like
julia> x = [ 1 2 3 ]
1x3 Array{Int64,2}:
1 2 3
julia> y = [ 3 2 1]
1x3 Array{Int64,2}:
3 2 1
julia> dot(x,y)
ERROR: `dot` has no method matching dot(::Array{Int64,2}, ::Array{Int64,2})
You might have used a 2d row vector where a 1d column vector was required.
Note the difference between 1d column vector [1,2,3] and 2d row vector [1 2 3].
You can convert to a column vector with the vec() function.
The error message suggestion is dot(vec(x),vec(y), but sum(x.*y) also works in this case and is shorter.
julia> sum(x.*y)
10
julia> dot(vec(x),vec(y))
10
Now, you can write x⋅y instead of dot(x,y).
To write the ⋅ symbol, type \cdot followed by the TAB key.
If the first argument is complex, it is conjugated.
Now, dot() and ⋅ also work for matrices.
Since version 1.0, you need
using LinearAlgebra
before you use the dot product function or operator.