StepRange description in Julia - julia

while working in julia programming, for creating an array instead of using a=[1:1:20...] i used a=[1:1:20] and it created an array saying "1-element Array{StepRange{Int64,Int64},1}".
What does this "1-element Array{StepRange{Int64,Int64},1}" mean? what StepRange means?

From the documentation of StepRange (type ?StepRange in the Julia REPL to see this):
StepRange{T, S} <: OrdinalRange{T, S}
Ranges with elements of type T with spacing of type S. The step
between each element is constant, and the range is defined in terms
of a start and stop of type T and a step of type S. Neither T nor S
should be floating point types. The syntax a:b:c with b > 1 and a,
b, and c all integers creates a StepRange.
So, for example
julia> typeof(1:1:20)
StepRange{Int64,Int64}
and
julia> [1:1:20]
1-element Array{StepRange{Int64,Int64},1}:
1:1:20
thus constructs a Vector (1D Array) containing one StepRange. If you want to materialize the lazy StepRange I would recommend collect(1:1:20) instead of using splatting ([1:1:20...]).
You can access start / step / stop fields of a StepRange using:
julia> r = 1:1:20
julia> r.start
1
julia> r.stop
20
julia> r.step
1

Related

Difference between Array and Vector

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

Julia: Set index at NTuple

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

Julia multidimensional array types?

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.

How to represent a performant heterogenous stack in Julia

I would like to implement a simple concatenative language (aka Joy or Factor) as a DSL in Julia and I am troubled how to optimally represent the stack.
The stack, which represents both data and program code, should be able to hold a sequence of items of different types. In the simplest case Ints, Symbols and, recursively again, stacks (to represent quoted code). The program will then heavily use push! and pop! to shuffle values between different such stacks.
One obvious implementation in Julia, which works but runs rather slow, is to use cell arrays. For example, the following Joy stack [ 1 [ 1 2 +] i + ] (which evaluates to [4]) can be implemented in Julia as
stack = Any[:+,:i,Any[:+,2,1],1]. My typical code then looks like this:
x = pop!(callstack)
if isa(x,Int)
push!(x,datastack)
elseif isa(x,Symbol)
do_stuff(x,datastack)
end
This, however, runs really slow and uses huge memory allocations, probably because such code is not typestable (which is a big performance bottleneck in Julia).
Using C, I would represent the stack compactly as an array (or alternatively as a linked list) of a union:
typedef union Stackelem{
int val;
char *sym;
union Stackelem *quote;
} Stackelem;
Stackelem stack[n];
But how can I achieve such a compact representation of the heterogeneous stack in Julia, and how I avoid the type instability?
This is one way, another way would be to represent args with type Vector{Any}:
julia> immutable Exp
head::Symbol
args::Tuple
end
julia> q = Exp(:+, (1, Exp(:-, (3, 4))))
Exp(:+,(1,Exp(:-,(3,4))))
edit: Another way to represent it might be:
immutable QuoteExp{T} ; vec::Vector{T} ; end
typealias ExpTyp Union{QuoteExp, Int, Symbol}
typealias Exp QuoteExp{ExpTyp}
and then you can do the following:
julia> x = Exp(ExpTyp[:+, 1, 2])
QuoteExp{Union{Int64,QuoteExp{T},Symbol}}(Union{Int64,QuoteExp{T},Symbol}[:+,1,2])
julia> x.vec[1]
:+
julia> x.vec[2]
1
julia> x.vec[3]
2
julia> push!(x.vec,:Scott)
4-element Array{Union{Int64,QuoteExp{T},Symbol},1}:
:+
1
2
:Scott
julia> x.vec[4]
:Scott

What is the best way to form inner products?

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.

Resources