Creating an array of `nothing` of any size in Julia - julia

In Julia it is possible to create arrays of any size using the functions zeros(.) or ones(.). Is there a similar function to create an array that is filled with nothing at initialization but also accepts floats? I mean a function like in this example:
a = array_of_nothing(3)
# a = [nothing,nothing,nothing]
a[1] = 3.14
# a = [3.14,nothing,nothing]
I tried to find information on internet, but without success... Sorry, I am a beginner in Julia.

The fill function can be used to create arrays of arbitrary values, but it's not so easy to use here, since you want a Vector{Union{Float64, Nothing}}. Two options come to mind:
A comprehension:
a = Union{Float64, Nothing}[nothing for _ in 1:3];
a[2] = 3.14;
>> a
3-element Array{Union{Nothing, Float64},1}:
nothing
3.14
nothing
Or ordinary array initialization:
a = Vector{Union{Float64, Nothing}}(undef, 3)
fill!(a, nothing)
a[2] = 3.14
It seems that when you do Vector{Union{Float64, Nothing}}(undef, 3) the vector automatically contains nothing, but I wouldn't rely on that, so fill! may be necessary.

I think you are looking for the Base.fill — Function.
fill(x, dims)
This creates an array filled with value x.
println(fill("nothing", (1,3)))
You can also pass a function Foo() like fill(Foo(), dims) which will return an array filled with the result of evaluating Foo() once.

Related

How to inherit from a regular matrix

using ShiftedArrays
struct CircularMatrix{T} <: AbstractArray{T,2}
data::Array{T,2}
view::CircShiftedArray
currentIndex::Int
function CircularMatrix{T}(dims...) where T
data = zeros(T, dims...)
CircularMatrix(data, ShiftedArrays.circshift(data, (0, -1)), 1)
end
end
Base.size(M::CircularMatrix) = size(M.data)
Base.eltype(::Type{CircularMatrix{T}}) where {T} = T
function shift_forward!(M::CircularMatrix)
M.shift_forward!(1)
end
function shift_forward!(M::CircularMatrix, n)
# replace the view with a view shifted forwards.
M.currentIndex += n
M.view = ShiftedArrays.circshift(M.data, (n, M.currentIndex))
end
#inline Base.#propagate_inbounds function Base.getindex(M::CircularMatrix, i) = M.view[i]
#inline Base.#propagate_inbounds function Base.setindex!(M::CircularMatrix, data, i) = M.view[i] = data
How can I make CircularMatrix act just like a regular matrix.
So that I can access it like
m = CircularMatrix{Int}(4,4)
m[1, 1] = 5
x = view(m, 1, :)
Your matrix type is defined to be a subtype of AbstractArray{T, 2}. You need to implement a few methods in the informal array interface of Julia for your type to make functions and features that work on AbstractArray{T, 2} to also work on your custom type, that is, to make your CircularMatrix an iterable, indexable, completely functioning matrix.
The methods to implement are
size(M::CircularMatrix)
getindex(M::CircularMatrix, i::Int)
getindex(M::CircularMatrix, I::Vararg{Int, N})
setindex!(M::CircularMatrix, v, i::Int)
setindex!(M::CircularMatrix, v, I::Vararg{Int, N})
You already implement 1, 2 and 4 but have not yet set your indexing style. You might not need 3 and 5 if you choose linear indexing style. You only need to set IndexStyle to be IndexLinear() and maybe a few modifications, then everything should just work for your matrix.
1. size(M::CircularMatrix)
The first one is size. size(A::CircularMatrix) returns a Tuple of dimensions of A. I believe for your matrix probably something like the following
Base.size(M::CircularMatrix) = size(M.data)
2. getindex(M::CircularMatrix, i::Int)
This method is needed if you choose linear indexing style. getindex(M, i::Int) should give you the value at linear index i. You already implement it in your code. If you choose linear indexing, you need to set IndexStyle for your type and then you simply skip 3 and 5. Julia will automatically convert multiple index accesses, e.g. a[3, 5], to a linear index access.
Base.IndexStyle(::Type{<:CircularMatrix}) = IndexLinear()
Base.#propogate_inbounds function Base.getindex(M::CircularMatrix, i::Int)
#boundscheck checkbounds(M, i)
#inbounds M.view[i]
end
It might be better to use #inbounds here on the second line. If the caller doesn't use #inbounds, we check the bounds first and this hopefully makes the subsequent bounds check unnecessary. You might want to omit this during development, though.
3. getindex(M::CircularMatrix, I::Vararg{Int, N})
The third one is for Cartesian indexing style. If you choose this style you need to implement this method. Vararg{Int, N} in the signature stands for "exactly N Int arguments". Here N should be equal to the dimensionality of CircularMatrix. Since this is a matrix, N should be two. If you choose this style, you need to define something like the following
Base.#propogate_inbounds function Base.getindex(A::CircularMatrix, I::Vararg{Int, 2})
#boundscheck checkbounds(A, I...)
#inbounds A.view[# convert I[1]` and `I[2]` to a linear index in `view`]
end
or since your dimensionality is not parametric and a matrix is 2D, simply
Base.#propogate_inbounds function Base.getindex(A::CircularMatrix, i::Int, j::Int)
#boundscheck checkbounds(A, i, j)
#inbounds A.view[# convert i` and `j` to a linear index in `view`]
end
4. setindex!(M::CircularMatrix, v, i::Int)
The fourth one is similar to the second. This method should set the value at linear index i, if you choose linear indexing style.
5. setindex!(M::CircularMatrix, v, I::Vararg{Int, N})
The fifth one should be similar to the third, if you choose Cartesian indexing style.
After the implementations for 1, 2, and 4 and setting IndexStyle, you should have a custom matrix type that just works.
m[1, 1] = 5
x = view(m, 1, :)
for e in
...
end
for i in eachindex(m)
...
end
display(m)
println(m)
length(m)
ndims(m)
map(f, A)
....
These should all work.
A few notes
There is a documentation for Abstract Arrays interface here with a few examples. You can also see Optional Methods to implement.
There is a JuliaArray organization on GitHub that provides lots of useful custom array implementations including StaticArrays, OffsetArrays, etc. and also a JuliaMatrices organization that provides custom matrix types. You might want to take a look at their implementations.
#inline is redundant if you use Base.#propogate_inbounds.
#propagate_inbounds
Tells the compiler to inline a function while retaining the caller's
inbounds context.
You do not need to define eltype for your matrix, since there is already a definition for AbstractArray{T, N} which returns T.

Store values generated by a for-loop. JuMP/Julia

It's amazing that the internet is totally void of this simple question (or similar). Or I'm just very bad at searching. Anyway, I simply want to store values generated by a for-loop in an array and print the array. Simple as that.
On every other language Matlab, R, Python, Java etc this is very simple. But in Julia I seem to be missing something.
using JuMP
# t = int64[] has also been tested
t = 0
for i in 1:5
vector[i]
println[vector]
end
I get the error
ERROR: LoadError: BoundsError
What am I missing?
You didn't initialize vector and you should call the method println like this following way, in Julia 1.0 :
vector = Array{Int,1}(undef, 5)
for i in 1:5
vector[i] = i
println(vector[i])
end
Or, more quickly, with a comprehension list :
vector = [i for i in 1:5]
for i in 1:5
println(vector[i])
end
Another possibility using push! method :
vector = []
for i in 1:5
push!(vector, i)
println(vector[i])
end

Accessing values in expression using a macro

I'm wondering whether it's possible to define a macro that can modify the values of an expression only if the values are of a specific type?
Here's a minimal example:
type Special
x::Int
end
f1(s, n::Special) = println("f1", s, n)
f2(s, n::Special) = println("f2", s, n)
x1 = Special(3)
x2 = Special(5)
expr = :(
f1("this is f1", x1),
f2("this is f2", x2)
)
Now a macro might be able to examine the values of the arguments to the functions, determine that x1 and x2 are of type Special, run some function to modify their values, say by changing 3 to 4 and 5 to 2 (it might involve comparing two values), then pass the expression back to the caller. The final result would be equivalent to calling:
f1("this is f1", 4)
f2("this is f2", 2)
I found that it's possible to access the values in a macro via:
eval(eval(filter(x -> typeof(eval(x)) == Special, expr.args[1].args))[1]).x
=> 3
but although this works it looks wrong, and I'm might either be doing it wrong or trying to do something too way out...
No, you should never try to check types or values inside macros. Using eval to figure out the type or value of something in a macro may work in very limited situations, but it'll break in almost every real use. Instead, just have the macro insert a call to a generic function — that's where Julia excels at picking apart types (as method dispatch) and values (within the method):
munge_special(x::Special) = Special(x.x + 42)
munge_special(x) = x
macro do_something_special(x)
return :(munge_special($(esc(x))))
end
julia> #do_something_special Special(2)
Special(44)
julia> #do_something_special 3
3

How can I interpret user input as a function in Julia?

I've been using the following function to take in user input for something I'm writing in Julia:
function input(prompt::AbstractString = "")
println(prompt * " ")
chomp(readline())
end
In my particular case, the input that I'm taking in is in the form of equations such as "y = x^2". After the input() function passes it to me as an ASCIIString, I then use the parse() function to convert it to an Expression:
:(y = x^2)
As an Expression, I can use the .args attribute to do things like counting the number of variables and returning the unique variables, all of which has worked fine. Now, I need to be able to evaluate the right side of the expression as the Function f(x) = x^2. To do so, I began writing the following function (which has some pretty major flaws):
function evalExpression()
L = [1,2,3,4]
equation = parse(input("Enter an equation"))
f = equation.args[2].args[2]
for i in L
x = i
value = eval(f)
println(value)
end
end
This function has two problems that I haven't been able to resolve. The first is that it gives me an UndefVarError for x when I try to run it right now; that's more or less expected. The second is that unless I knew that the user would input a function of only x, I would have no way of figuring out what the variables I needed to assign were. I wrote a recursive function that can take in an expression and return all its variables in the form of [:x, :y, etc.], but I cannot assign :x to a number to evaluate the function--I need to assign it just to x, and I cannot figure out how to access that. Is there anything that I can use to access the variables I need? Or a different approach I could take?
Thank you!
When I run the following:
function evalExpression()
L = [1,2,3,4]
equation = parse(input("Enter an equation"))
global x
for i in L
x = i
f = equation.args[2].args[2]
value = eval(f)
println(value)
end
end
and then putting y = x*x I get
evalExpression()
Enter an equation
y = x*x
1
2
3
4
What is missing, at least for x as a variable, is declaring it globally. When you eval parsed statements, these parsed statements only access global variables
So what you probably need to do after you've invented your recursive function to correctly fetch variables, is to create them globally. Maybe
eval(parse("$variable = 0"))
will do

Julia: append to an empty vector

I would like to create an empty vector and append to it an array in Julia. How do I do that?
x = Vector{Float64}
append!(x, rand(10))
results in
`append!` has no method matching append!(::Type{Array{Float64,1}}, ::Array{Float64,1})
Thanks.
Your variable x does not contain an array but a type.
x = Vector{Float64}
typeof(x) # DataType
You can create an array as Array(Float64, n)
(but beware, it is uninitialized: it contains arbitrary values) or zeros(Float64, n),
where n is the desired size.
Since Float64 is the default, we can leave it out.
Your example becomes:
x = zeros(0)
append!( x, rand(10) )
I am somewhat new to Julia and came across this question after getting a similar error. To answer the original question for Julia version 1.2.0, all that is missing are ():
x = Vector{Float64}()
append!(x, rand(10))
This solution (unlike x=zeros(0)) works for other data types, too. For example, to create an empty vector to store dictionaries use:
d = Vector{Dict}()
push!(d, Dict("a"=>1, "b"=>2))
A note regarding use of push! and append!:
According to the Julia help, push! is used to add individual items to a collection, while append! adds an collection of items to a collection. So, the following pieces of code create the same array:
Push individual items:
a = Vector{Float64}()
push!(a, 1.0)
push!(a, 2.0)
Append items contained in an array:
a = Vector{Float64}()
append!(a, [1.0, 2.0])
You can initialize an empty Vector of any type by typing the type in front of []. Like:
Float64[] # Returns what you want
Array{Float64, 2}[] # Vector of Array{Float64,2}
Any[] # Can contain anything
New answer, for Julia 1. append! is deprecated, you now need to use push!(array, element) to add elements to an array
my_stuff = zeros()
push!(my_stuff, "new element")

Resources