# Ref vs zero-dimensional arrays?

**URL:** <https://discourse.julialang.org/t/ref-vs-zero-dimensional-arrays/24434>\
**Category:** General Usage\
**Tags:** question\
**Created:** [May 21, 2019, 2:01pm UTC](https://discourse.julialang.org/t/ref-vs-zero-dimensional-arrays/24434 "2019-05-21T14:01:54Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [May 21, 2019, 2:01pm UTC](https://discourse.julialang.org/t/ref-vs-zero-dimensional-arrays/24434/1 "2019-05-21T14:01:54Z")

</div>

What is the difference between a zero-dimensional array holding the value `x`, which you construct using `fill(x)`, and a `Ref(x)`?

In both cases you would access the underlying data via `[]`, which can be set or read.  
And it seems that both store a pointer to the actual data.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [May 21, 2019, 2:05pm UTC](https://discourse.julialang.org/t/ref-vs-zero-dimensional-arrays/24434/2 "2019-05-21T14:05:18Z")

</div>

> [@e3c6](#):
>
> What is the difference between a zero-dimensional array holding the value `x` , which you construct using `fill(x)` , and a `Ref(x)` ?

```julia
julia> typeof(fill('a'))
Array{Char,0}

julia> typeof(Ref('a'))
Base.RefValue{Char}

```

> [@e3c6](#):
>
> In both cases you would access the underlying data via `[]` , which can be set or read.

Correct, but this does not mean that they are the same thing.

> [@e3c6](#):
>
> And it seems that both store a pointer to the actual data.

They don’t — the concept of pointers is not helpful in understanding composite types or containers in Julia.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [May 21, 2019, 2:21pm UTC](https://discourse.julialang.org/t/ref-vs-zero-dimensional-arrays/24434/3 "2019-05-21T14:21:53Z")

</div>

One is an array — which means that it supports a bit more arithmetic and such like:

```julia
julia> fill(1) + fill(2)
3

```

Ref is about as barebones of a 0-dimensional container as you can get. But just like all 0-dimensional containers, it’ll work nicely with broadcast.

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [May 21, 2019, 2:27pm UTC](https://discourse.julialang.org/t/ref-vs-zero-dimensional-arrays/24434/4 "2019-05-21T14:27:53Z")

</div>

I typically use them to have a simple (quick and dirty) modifiable field in a `struct` or for a pass-by-reference argument into a function. I presume there is no real performance difference between using one or the other in such a case?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [May 21, 2019, 2:35pm UTC](https://discourse.julialang.org/t/ref-vs-zero-dimensional-arrays/24434/5 "2019-05-21T14:35:56Z")

</div>

`Ref` is an abstract type so can have performance overhead if stored in a `struct`.

```julia
julia> struct S
           s::Ref{Int}
       end

julia> b = S(1)
S(Base.RefValue{Int64}(1))

julia> f(b) = b.s[]
f (generic function with 1 method)

julia> @code_warntype f(b)
Variables
  #self#::Core.Compiler.Const(f, false)
  b::S

Body::Any
1 ─ %1 = Base.getproperty(b, :s)::Ref{Int64}
│ %2 = Base.getindex(%1)::Any
└── return %2

```

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [May 21, 2019, 2:54pm UTC](https://discourse.julialang.org/t/ref-vs-zero-dimensional-arrays/24434/6 "2019-05-21T14:54:21Z")

</div>

`Array` is always a pretty fat `jl_array` from the runtime, always heap allocated, etc.

In contrast, `RefValue` is almost the same as a mutable struct with a single field plus convenience access functions. This means that the optimizer can see through `Ref`, and often stack allocate it or refuse to allocate it alltogether.

An especially important idiom is to use `unsafe_store!` / `unsafe_load` on `pointer_from_objref` on refs in order to fiddle with bits / reinterpret between arbitrary bitstypes. The compiler is quite good at optimizing out that kind of stuff. This would not work with Array.

---

<div class="post-metadata">

**Author:** ![e3c6](https://avatars.discourse-cdn.com/v4/letter/e/e79b87/32.png) [@e3c6](https://discourse.julialang.org/u/e3c6)\
**Post date:** [May 21, 2019, 3:10pm UTC](https://discourse.julialang.org/t/ref-vs-zero-dimensional-arrays/24434/7 "2019-05-21T15:10:15Z")

</div>

I guess one can use

```julia
struct S
    s::Base.RefValue{Int}
end
S(x::Int) = S(Ref(x))

```

instead. Then

```julia
julia> @code_warntype f(b)
Body::Int64
1 ─ %1 = (Base.getfield)(b, :s)::Base.RefValue{Int64}
│ %2 = (Base.getfield)(%1, :x)::Int64
└── return %2

```

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [May 21, 2019, 4:05pm UTC](https://discourse.julialang.org/t/ref-vs-zero-dimensional-arrays/24434/8 "2019-05-21T16:05:15Z")

</div>

> [@e3c6](#):
>
> I guess one can use […]

yep, that’s one level of pointer indirection less than `Array`. However, `mutable struct S s::Int end` is still one less level of pointer indirection (and one less allocation).

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [May 21, 2019, 4:47pm UTC](https://discourse.julialang.org/t/ref-vs-zero-dimensional-arrays/24434/9 "2019-05-21T16:47:13Z")

</div>

> [@mbauman](#):
>
> Ref is about as barebones of a 0-dimensional container as you can get. But just like all 0-dimensional containers, it’ll work nicely with broadcast.

I think that `Ref`was hijacked incidentally for this purpose, possibly following [this suggestion](https://github.com/JuliaLang/julia/issues/18271#issuecomment-245276731). Cf

> <https://github.com/JuliaLang/julia/issues/18379>
>
> I found myself needing a \`Scalar\` type for broadcasting purposes, to trick \`broa…dcast\` into \_not\_ trying to broadcast something, even though it is a matrix. An initial (bad) implementation is \[here\](https://github.com/TotalVerb/Scalars.jl).
> 
> With https://github.com/JuliaLang/julia/pull/16986 close to merging, I wonder if such a feature would be desirable in \`Base\`.

On 1.2-pre, `?Ref` still does not mention that it has anything to do with broadcasting.

In retrospect I think that this choice was unfortunate, as it conflates semantics. Also, I am not sure that many users are aware that `Ref{T}` is not a concrete type.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [May 21, 2019, 5:06pm UTC](https://discourse.julialang.org/t/ref-vs-zero-dimensional-arrays/24434/10 "2019-05-21T17:06:02Z")

</div>

Just the other day a colleague asked me how to make something behave as a scalar under broadcasting. I showed him `Ref` and he was suprised that he couldn’t find anything about it in the docs.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [May 21, 2019, 5:08pm UTC](https://discourse.julialang.org/t/ref-vs-zero-dimensional-arrays/24434/11 "2019-05-21T17:08:59Z")

</div>

`Ref` doesn’t really have anything to do with broadcasting. It’s just a convenient, short-named zero-dimensional container that doesn’t have the overhead of the `Array` header. As long as Ref is a zero-dimensional container, I don’t see any conflating of semantics. Now, that view isn’t entirely historically accurate, as Refs were indeed previously “hijacked” and special-cased to behave like 0-dimensional arrays only for the purposes of broadcast, but these days _they really are_ 0-dimensional like and they just behave appropriately.

I was imagining that `Ref` would only be transiently visible to users until the `&x` syntax landed, but that got tied up and slogged down. I’d still love to see that, then the choice of how we implement scalars would be entirely internal. It’s indeed the `&x` syntax that could unites the ccall and broadcast use-cases.

You can also use `(x,)` or `[x]` as 1-tuples and 1-vectors also broadcast (almost) entirely like scalars. The tuple will of course be more efficient than the vector.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [May 21, 2019, 5:54pm UTC](https://discourse.julialang.org/t/ref-vs-zero-dimensional-arrays/24434/12 "2019-05-21T17:54:23Z")

</div>

I meant that `Ref` is now the _de facto_ solution for escaping broadcasting.

You are of course right, and indeed any 0-dimensional container would do, so in this sense `Ref` isn’t special, but in practice `Ref` has assumed this role.

It would be somewhat cleaner if we had something like `Scalar` proposed in the above PR, with the sole purpose of just escaping broadcasting, and no shared meaning with anything else. This a style question, but I think an important one.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [April 12, 2025, 11:42am UTC](https://discourse.julialang.org/t/ref-vs-zero-dimensional-arrays/24434/13 "2025-04-12T11:42:46Z")

</div>

Made a package to supplant non-FFI uses of `Ref`:

> [@\[ANN\]: ZeroDimensionalArrays.jl: zero-dimensional arrays/references/boxes](https://discourse.julialang.org/t/ann-zerodimensionalarrays-jl-zero-dimensional-arrays-references-boxes/128002):
>
> [ZeroDimensionalArrays.jl](https://github.com/JuliaArrays/ZeroDimensionalArrays.jl) is being registered, meaning it has entered the three-day-long wait period. Feel free to suggest breaking changes until the wait period is over! It’s a tiny package, implementing several similar types, each being a zero-dimensional array. The package is a response to the frequent confusion regarding Ref because of the semantic overloading, and the fact that Julia programmers often don’t expect Ref to be an abstract type. It’s meant to replace most/all non-ccall-related…
