# StaticArrays field values printed as undef?

**URL:** <https://discourse.julialang.org/t/staticarrays-field-values-printed-as-undef/56318>\
**Category:** New to Julia\
**Created:** [March 2, 2021, 10:48am UTC](https://discourse.julialang.org/t/staticarrays-field-values-printed-as-undef/56318 "2021-03-02T10:48:01Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![paulmelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paulmelis/32/35063_2.png) [@paulmelis](https://discourse.julialang.org/u/paulmelis)\
**Post date:** [March 2, 2021, 10:48am UTC](https://discourse.julialang.org/t/staticarrays-field-values-printed-as-undef/56318/1 "2021-03-02T10:48:02Z")

</div>

I’m using a StaticArrays.jl `FieldVector` for a 3-vector that can be both accessed by field name (`v.x`) as well as by index (`v[1]`). I also added a `length` function to get the vector length:

```julia
using StaticArrays
using LinearAlgebra

struct vec3 <: FieldVector{3, Float32}
    x::Float32
    y::Float32
    z::Float32
    
    vec3() = zeros(Float32, 3)
    vec3(x, y, z) = new(x, y, z)
end

import Base.length
length(v::vec3) = sqrt(dot(v,v))

v = vec3(0.5f0, 0.0f0, 0.5f0)

println(v)
println(v[1], v.x)
println(length(v))

```

The `import Base.length` seems to screw up the printing of `v`, as I get the following output:

```julia
Float32[#undef, #undef, #undef]
0.50.5
0.70710677

```

The first line suggests the vector fields have an undefined value, but the other two lines show the values are actually correct, they’re merely printed incorrectly. Removing the `import Base.length` line fixes this and produces:

```julia
Float32[0.5, 0.0, 0.5]
0.50.5
0.70710677

```

Is this an expected side-effect of the import, or a bug?

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [March 2, 2021, 10:54am UTC](https://discourse.julialang.org/t/staticarrays-field-values-printed-as-undef/56318/2 "2021-03-02T10:54:41Z")

</div>

`Base.length` should always return the number of elements in an array, breaking this assumption for your own `AbstractArray` type is expected to cause problems. It looks like you just want `norm` from `LinearAlgebra` here?

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [March 2, 2021, 11:08am UTC](https://discourse.julialang.org/t/staticarrays-field-values-printed-as-undef/56318/3 "2021-03-02T11:08:23Z")

</div>

> [@paulmelis](#):
>
> `vec3() = zeros(Float32, 3)`

I don’t think this is what you want:

```julia
jl> vec3()
3-element Vector{Float32}:
 0.0
 0.0
 0.0

```

I think you should use

```julia
vec3() = new(0f0, 0f0, 0f0)
# or
vec3() = vec3(0f0, 0f0, 0f0)

```

---

<div class="post-metadata">

**Author:** ![paulmelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paulmelis/32/35063_2.png) [@paulmelis](https://discourse.julialang.org/u/paulmelis)\
**Post date:** [March 2, 2021, 11:21am UTC](https://discourse.julialang.org/t/staticarrays-field-values-printed-as-undef/56318/4 "2021-03-02T11:21:21Z")

</div>

> [@simeonschaub](#):
>
> `Base.length` should always return the number of elements in an array, breaking this assumption for your own `AbstractArray` type is expected to cause problems. It looks like you just want `norm` from `LinearAlgebra` here?

Ah, didn’t realize `vec3` ends up being an `AbstractArray`, but that makes sense of course.

```julia
julia> supertypes(vec3)
(vec3, FieldVector{3,Float32}, FieldArray{Tuple{3},Float32,1}, StaticArray{Tuple{3},Float32,1}, AbstractArray{Float32,1}, Any)

```

I indeed noticed `norm` was working anyway as an alternative, but was wondering what was going on here.

> [@DNF](#):
>
> I don’t think this is what you want:
> 
> ```julia
> jl> vec3()
> 3-element Vector{Float32}:
> 0.0
> 0.0
> 0.0
> 
> ```

So even though I declared `vec3()` as an inner constructor it can still return any type at all? Ugh.

Thanks to both of you!

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [March 2, 2021, 11:48am UTC](https://discourse.julialang.org/t/staticarrays-field-values-printed-as-undef/56318/5 "2021-03-02T11:48:29Z")

</div>

> [@paulmelis](#):
>
> So even though I declared `vec3()` as an inner constructor it can still return any type at all? Ugh.

Well, you explicitly specified that it should be `zeros(Float32, 3)`, and without passing it through `new`, so the compiler doesn’t have much choice. Maybe there could be a warning or something.

I think the special thing with inner constructors is that they have access to `new`, but if you don’t use it, that doesn’t matter. In fact, I don’t think `vec3` should be an inner constructor, it should be outer, and just call `vec3(0f0,0f0,0f0)`.

---

<div class="post-metadata">

**Author:** ![paulmelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paulmelis/32/35063_2.png) [@paulmelis](https://discourse.julialang.org/u/paulmelis)\
**Post date:** [March 2, 2021, 3:09pm UTC](https://discourse.julialang.org/t/staticarrays-field-values-printed-as-undef/56318/6 "2021-03-02T15:09:44Z")

</div>

> [@DNF](#):
>
> I think the special thing with inner constructors is that they have access to `new` , but if you don’t use it, that doesn’t matter.

Right, not forgetting to use `new()` is crucial 🙂 . But it’s also a bit surprising that a constructor that is defined within a struct can construct something that is of a different type unrelated to the struct.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [March 2, 2021, 3:55pm UTC](https://discourse.julialang.org/t/staticarrays-field-values-printed-as-undef/56318/7 "2021-03-02T15:55:51Z")

</div>

One extra thing, though: even if the constructor automatically converted to the correct type, it would still have to go through an ordinary `Array` first, which would be very inefficient.

Sometimes I’ve seen people construct `SArray`s by creating an ordinary array and then converting it, like you tried. This should be avoided, always make sure to directly create an `SArray`.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [March 2, 2021, 4:33pm UTC](https://discourse.julialang.org/t/staticarrays-field-values-printed-as-undef/56318/8 "2021-03-02T16:33:38Z")

</div>

> [@paulmelis](#):
>
> So even though I declared `vec3()` as an inner constructor it can still return any type at all? Ugh.

Maybe a construction like this is more interesting:

```julia
julia> struct vec3{T} <: FieldVector{3,T}
           x::T
           y::T
           z::T
       end

julia> zero(vec3{Float32})
3-element vec3{Float32} with indices SOneTo(3):
 0.0
 0.0
 0.0

```

Or, if you know that you will never use anything else than `Float32`, just

```julia
julia> struct vec3 <: FieldVector{3,Float32}
           x::Float32
           y::Float32
           z::Float32
       end

julia> zero(vec3)
3-element vec3 with indices SOneTo(3):
 0.0
 0.0
 0.0

```

Note that that type of structure allows you to write generic functions, like this:

```julia
julia> function f(x::Vector{T}) where T
          y = zero(T)
          for v in x
             y += v
          end
          y
       end
f (generic function with 1 method)

julia> x = [rand(vec3{Float32}) for i in 1:3];

julia> f(x)
3-element vec3{Float32} with indices SOneTo(3):
 0.16435432
 1.3771235
 1.274611

julia> x = [1, 2, 3];

julia> f(x)
6

```

Thus if you decide to use `vec2` or `vec4` you don’t need to rewrite any of the functions.
