What does [] mean in this case?

I’m trying to figure out a functionality of Makie.jl, which I can’t find in documentation. In the process, I noticed a syntax I don’t understand:

julia> s = Scene()

julia> fieldnames(Scene)
(:parent, :events, :px_area, :clear, :camera, :camera_controls, :data_limits, :transformation, :plots, :theme, :attributes, :children, :current_screens, :updated)

julia> typeof(s.update_limits[])
Bool

What does update_limits[] mean syntactically? It is not a field of Scene struct and I can’t find this use of [] in the documentation.

1 Like

Is update_limits a Ref?

julia> x = Ref{Int}()
Base.RefValue{Int64}(0)

julia> x[] = 1
1

julia> x
Base.RefValue{Int64}(1)

julia> x[]
1

getindex without the indices is the generic syntax to access the only element of a single-element container, a Ref but also a plain Array:

julia> x = [1]
1-element Array{Int64,1}:
 1

julia> x[]
1

julia> getindex(x)
1
4 Likes

I don’t know:

julia> typeof(s.update_limits)
Observable{Any}

Thank you for pointing me towards references. The search engine for Julia manual is helpless with "[]" or [] search queries. I get zero or 152 unrelated results.

2 Likes

I assume this is from Observables.jl? If so, quoting from the documentation:

5 Likes

Nice @giordano, learned something new today :slight_smile:

Is it correct to say that a[] is also better than a[1] because it is converted to a[begin]? So it uses the correct firstindex for the collection?

I wouldn’t encourage using a[] for arrays, a[begin] is more explicit and clear, albeit a bit verbose (and I think requires Julia v1.something, with something != 0). But for single-element arrays maybe it’s fine anyway :thinking:

Edit: the problem of [] is that it breaks with containers with more than one element:

julia> x = [1, 2]
2-element Array{Int64,1}:
 1
 2

julia> x[]
ERROR: BoundsError: attempt to access 2-element Array{Int64,1} at index []

So you must be sure that the container has a single element in order to use it. For Ref-like containers this is usually the case (they have by design only one element, just make sure the object is always a Ref), but for arrays that can grow this assumption may be wrong.

4 Likes

How does

s = S()
s.aname[]

work when aname is not a field name of type S?

1 Like

That’s a feature! It’s wholly consistent with how omitting indexing dimensions work in general. In other words, it’s a nice shorthand for grabbing the only element — and ensuring that there’s only one.

6 Likes

I didn’t want to imply that’s a bug, only point out that if you expect to work with any container (of any size!) you can have problems :slightly_smiling_face:

2 Likes

It would help if this statement in the manual:

When omitting all indices with A[], this semantic provides a simple idiom to retrieve the only element in an array and simultaneously ensure that there was only one element.

was searchable with [] query.

1 Like

While technically it works, I find it somewhat obscure to rely on [] doing this.

I would suggest only instead, which was explicitly introduced in 1.4 for this.

6 Likes

Nice to learn about only as well, though I think that [] may be nicer in some contexts like many observables lifted in a Makie.jl visualization for example. Placing only everywhere can pollute the code.

Observables are guaranteed to only have one item and using [] is perfectly natural for them. only is to be used on e.g. a Vector where you expect it to only have one item after e.g. some filtering step.

8 Likes

I would only use [] on “zero-dimensional” containers (e.g. Ref, zero-dimensional arrays, Observable, and similar objects), where passing an index doesn’t make sense and they are guaranteed to contain exactly one element.

5 Likes