ERROR: LoadError: indexed assignment not defined for FloatRange{Float64}

Why does this not work:

xVector=0:0.01:2*pi;
yVector=0.0*xVector;
for n=1:length(xVector)
yVector[n] = sin(xVector[n])
end
plot(xVector, yVector)

What is the correct way to do this?

yVector = similar(xVector)

1 Like

A couple of options

X = 0:0.01:2pi
Y = similar(X);
for i in eachindex(X) # or 1:length(X)
    Y[i] = sin(X[i])
end
plot(X, Y)

or

X = 0:0.01:2pi
Y = similar(X);
Y .= sin.(X)

Or to avoid writing the loop explicitly

yVector = sin.(xVector)

2 Likes

****** Thank you! ******

a:b:c does not create a vector. It creates a Range, which is a type that looks and indexes like a vector, but actually doesn’t allocate the memory for the vector. So indexing it is essentially calling a function, and it computes what the value should be, instead of storing it. When you get that, then you see why you cannot “set” values for it.

But, for these kinds of “lazy collections” (of which LinSpace is another), you can always collect them to a Vector via collect(a:b:c). Then you have a proper array which can set values, but now it takes up more memory (and is thus slower in practice, so don’t just collect everything like MATLAB!)

Hope that makes sense.

2 Likes

Very good explanation. Now it is crystal clear, thank you!

Maybe the error message could be improved? Currently

julia> xx = 0:0.1:2
0.0:0.1:2.0

julia> xx[3] = 5
ERROR: indexing not defined for FloatRange{Float64}
Stacktrace:
 [1] setindex!(::FloatRange{Float64}, ::Int64, ::Int64) at .\abstractarray.jl:873

julia> xx[3]
0.2

It’s confusing because “indexing” looks like it is defined – as in, indexed-get works. And the eltype is irrelevant to the problem.
Would an error message like the following be a good idea?

julia> xx[3] = 5
ERROR: indexed-set not defined for FloatRange, try making a copy with `collect` or `similar`

Thank you very much