Yeah, as john said the
state_values is not an array, although it “behaves” like one for most purposes.
In general, you are better off leaving things in their more abstract form as long as possible since otherwise you lose structure that can lead to better algorithms. Most julia algorithms will work just as well with a range as with a concrete array so you probably won’t even notice. Why is it different? A small point here is that there is essentially no storage in the
state_values other than the starting point, the step-size, and the number of elements. If you convert it to a vector it will both need a vector to have all of those values (which is probably irrelvant for small ones like this simple example, but this is a serious issue for larger ranges), but the ore important problem is that it loses the structure that this is a uniformly spaced vector.
Where would that be useful? Well, occasionally when iterating through it the compiler can use it to radically speed things up but the bigger consideration is that it allows specialized algorithms. For example, interpolating with Convenience Constructors · Interpolations.jl would do something different if you pass in a range,
1.0:0.01:2.0, vs. a vector,
collect(1.0:0.01:2.0)which it can’t know would be regularly spaced. In fact, there isn’t even a cubicspline feature in that package for irregularly spaced grids so it wouldn’t work at all if you pass it in after converting to a vector.
If you can handle the state and transition as being the same names as the fields, then since Julia 1.7, the canonical way of doing this sort of thing is
(; state_values, p) = mc
if you want to extract those. Or pre julia 1.7 you will see things using the Parameters/Unpack macro all over the place in people’s code
@unpack state_values, p = mc
This isn’t strictly necessary, of course, but the style is pervasive in Julia. The main benefit is that the lack of repetition leads to what you would call “defensive programming” to make bugs less likely
For example, spot what is wrong with unpacking this datastructure with a few more fields:
field_c, field_d, field_a, field_b = mc.field_c, mc.field_a, mc.field_d, mc.field_b
(;field_c, field_d, field_a, field_b) = mc
It becomes very easy to accidentally mismatch the order of the fields in the first case - especially if you are adding/removing a bunch of them and forget to swap the order on both sides. But as I said, these are small stylistic things which you don’t need to apply religiously (and has no impact on performance either way).