In Julia, how does one initialize an array to store mutable structs? For example:
mutable struct Foo
func # Some function
end
function Bar(param1, param2)
function nestedFunc(param3)
return param3
end
return Foo(nestedFunc)
end
# Initializing with 0s will throw an error when
# I attempt to store the struct returned in the Bar call below
arr = zeros(5, 5)
for i in 1:5
for j in 1:5
arr[i, j] = Bar(i, j)
end
end
I've also tried to initialize an array of type Any
, as arr = Array{Any, (5, 5)}
, but again, when setting the index I get something like ERROR: LoadError: MethodError: no method matching setindex!
How can I do this, and what is the rationale for this behavior I'm seeing? In Python, I can arbitrarily initialize a list and set almost anything I want within a particular index.
You can do what you want if you initialize your array as:
arr = Array{Foo,2}(undef,5,5)
In this example you are creating an array in which each element can be of type Foo, and it has two dimensions. The parameters passed to this "constructor" are undef, which tells that all the elements are not initialized, and the size of the two dimensions. You can check The section Construction and initialization of the Arrays section of the Julia manual.
If you are looking for the flexibility of a python list in which you can put objects of whatever type, you can do
arr = Array{Any,2}(undef,5,5)
In this case, the Any specifies that the elements of the Array can be of any type.
However, you should know that this is probably a bad method if you need performance, as having arrays with elements of type 'Any' prevents Julia from creating efficient code for your arrays.
You were creating an array with elements of type Float64, and you were trying to assing a function to these elements. You cannot change the type of the array on the fly. Having a defined type for the elements, allows julia to have an efficient way of saving things in memory and also allows the compiler to use fast functions when you do operations on arrays. Take a look at the Types section of the Julia manual
This is because you were not using a correct form for the initializer. The correct form is the one I showed.
P.S Are you sure you can do this with numpy arrays?
I just tried
import numpy as np
a = np.zeros(5)
a[0] = 'hello'
and got a type error similar to the one you see in Julia:
ValueError: could not convert string to float: 'hola'
Tip: never use untyped containers unless you really have to (usually you almost never have to)
Here is the correct way to do it (I have shortened bar
for readability, function names should start with small letters):
mutable struct Foo
func::Function
end
function bar(param1, param2)
nestedFunc(param3) = param3
return Foo(nestedFunc)
end
And now
julia> myarr = [bar(i,j) for i in 1:3, j in 1:4]
3×4 Array{Foo,2}:
Foo(nestedFunc) Foo(nestedFunc) Foo(nestedFunc) Foo(nestedFunc)
Foo(nestedFunc) Foo(nestedFunc) Foo(nestedFunc) Foo(nestedFunc)
Foo(nestedFunc) Foo(nestedFunc) Foo(nestedFunc) Foo(nestedFunc)
Another option (note that round parenthesis ()
make a generator and dot .
vectorizes the assignment operator):
myarr2 =Matrix{Foo}(undef,3,4)
myarr2 .= (bar(i,j) for i=1:3, j=1:4)
And the longest option (notet that the container is typed):
myarr3 =Matrix{Foo}(undef,3,4)
for i=1:3, j=1:4
myarr3 = bar(i,j)
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With