# Ref is not a concrete type - poorly documented?

**URL:** <https://discourse.julialang.org/t/ref-is-not-a-concrete-type-poorly-documented/120375>\
**Category:** Performance\
**Tags:** question, documentation\
**Created:** [September 28, 2024, 2:40pm UTC](https://discourse.julialang.org/t/ref-is-not-a-concrete-type-poorly-documented/120375 "2024-09-28T14:40:22Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![johnomotani](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnomotani/32/26753_2.png) [@johnomotani](https://discourse.julialang.org/u/johnomotani)\
**Post date:** [September 28, 2024, 2:40pm UTC](https://discourse.julialang.org/t/ref-is-not-a-concrete-type-poorly-documented/120375/1 "2024-09-28T14:40:22Z")

</div>

I just learned from [Why are ref's in structs type unstable?](https://discourse.julialang.org/t/why-are-refs-in-structs-type-unstable/80041) that `Ref` is not a concrete type, and so `struct`s containing a `Ref` are not type-stable, e.g.

```julia
struct Foo
  a::Ref
end

```

Instead you have to use, for example, `RefValue` like

```julia
struct Bar
  a::RefValue
end

```

As a new-ish user, who was introduced to `Ref` as “if you have to use a mutable, global variable, make it a `const Ref` so that it is type stable” (I know this is out of date now, since we can now declare types for global variables), it was surprising that putting a `Ref` in a `struct` is type unstable.

The documentation for `Core.Ref` ([C Interface · The Julia Language](https://docs.julialang.org/en/v1/base/c/#Core.Ref)) does implicitly tell you this, as it has an example

```julia
julia> Ref(5)
Base.RefValue{Int64}(5)

```

where you can see that the concrete type is `Base.RefValue` rather than `Ref`, but there is no explicit discussion and no warning about type instability.

**Question: what is best practice for using `Ref`, and should it be documented more clearly?**

In a quick search, the Discourse topic linked above was the only discussion I found about `Ref` and type stability, and the only documentation for `Ref` seems to be the docstring - did I miss something? If not, I think more guidance for usage would be good.

For a bit more detail on why I care: I’ve fallen into a pattern where when I want a mostly immutable struct, but one or two fields need to be mutable, I’ve made those fields `Ref` variables, assuming that this was a safe and sensible thing to do. Is this bad practice? Should I just use a `mutable struct` instead? Is using `Base.RefValue` instead of `Ref` the right thing to do?  
As `Base.RefValue` is not exported from `Base`, it doesn’t seem like an obvious thing to choose as a user!

---

<div class="post-metadata">

**Author:** ![DanielVandH](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielvandh/32/31134_2.png) [@DanielVandH](https://discourse.julialang.org/u/DanielVandH)\
**Post date:** [September 28, 2024, 2:45pm UTC](https://discourse.julialang.org/t/ref-is-not-a-concrete-type-poorly-documented/120375/2 "2024-09-28T14:45:45Z")

</div>

I made an issue for this a bit ago too [Ref docstring should note clearly that it's an abstract type · Issue #55321 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/55321). I don’t really understand some of the responses made in that issue but hopefully this can be addressed at some point. Maybe commenting your support for the matter in that issue could be useful as well.

---

<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:** [September 28, 2024, 3:03pm UTC](https://discourse.julialang.org/t/ref-is-not-a-concrete-type-poorly-documented/120375/3 "2024-09-28T15:03:15Z")

</div>

> [@johnomotani](#):
>
> I’ve fallen into a pattern where when I want a mostly immutable struct, but one or two fields need to be mutable

`struct`s may have `mutable struct` fields.

---

<div class="post-metadata">

**Author:** ![johnomotani](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnomotani/32/26753_2.png) [@johnomotani](https://discourse.julialang.org/u/johnomotani)\
**Post date:** [September 28, 2024, 3:07pm UTC](https://discourse.julialang.org/t/ref-is-not-a-concrete-type-poorly-documented/120375/4 "2024-09-28T15:07:16Z")

</div>

@nsajko are you saying that I should replace

```julia
struct Bar
  a::RefValue{Int64}
end

```

with

```julia
mutable struct BazSubStruct
  b::Int64
end
struct Baz
  a::BazSubStruct
end

```

?

That seems like quite a bit of boiler-plate code, which I’d only bother with if it was performance critical…

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [September 28, 2024, 3:09pm UTC](https://discourse.julialang.org/t/ref-is-not-a-concrete-type-poorly-documented/120375/5 "2024-09-28T15:09:32Z")

</div>

The other option that is available as of Julia 1.10 (iirc might be 1.9) is to make a mutable struct with const fields.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [September 28, 2024, 3:11pm UTC](https://discourse.julialang.org/t/ref-is-not-a-concrete-type-poorly-documented/120375/6 "2024-09-28T15:11:30Z")

</div>

I just really don’t get why we can’t just at least export `RefValue`. The reasoning, and preference for requiring users to define whole new structs is just bizarre and user-hostile to me.

---

<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:** [September 28, 2024, 3:19pm UTC](https://discourse.julialang.org/t/ref-is-not-a-concrete-type-poorly-documented/120375/7 "2024-09-28T15:19:51Z")

</div>

> [@johnomotani](#):
>
> That seems like quite a bit of boiler-plate code, which I’d only bother with if it was performance critical…

Personally I don’t see that as an issue at all. Another alternative is to use a zero-dimensional array, e.g., `Array{Int,0}`.

NB: mutable state is often a bad choice anyway

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [September 28, 2024, 3:37pm UTC](https://discourse.julialang.org/t/ref-is-not-a-concrete-type-poorly-documented/120375/8 "2024-09-28T15:37:53Z")

</div>

Zero dimensional arrays are worse, slower, and heavier than `RefValue`s.

---

<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:** [September 28, 2024, 3:46pm UTC](https://discourse.julialang.org/t/ref-is-not-a-concrete-type-poorly-documented/120375/9 "2024-09-28T15:46:15Z")

</div>

They’re supported, though.

If this is such an issue, why not implement a zero dimensional array type as a simple `mutable` wrapper:

```julia
mutable struct A{T} <: AbstractArray{T, 0}
    value::T
end
Base.getindex(a::A) = a.value
...

```

Then put it in a package and register it.

---

<div class="post-metadata">

**Author:** ![DanielVandH](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielvandh/32/31134_2.png) [@DanielVandH](https://discourse.julialang.org/u/DanielVandH)\
**Post date:** [September 28, 2024, 3:54pm UTC](https://discourse.julialang.org/t/ref-is-not-a-concrete-type-poorly-documented/120375/10 "2024-09-28T15:54:55Z")

</div>

I don’t think someone should have to make such a package when a perfectly fine `RefValue` exists, other than it not being public for whatever reason. People already use `Ref` for this (and not necessarily knowing about `RefValue` due to poor documentation).

---

<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:** [September 28, 2024, 4:24pm UTC](https://discourse.julialang.org/t/ref-is-not-a-concrete-type-poorly-documented/120375/11 "2024-09-28T16:24:28Z")

</div>

> [@DanielVandH](#):
>
> a perfectly fine `RefValue` exists, other than it not being public for whatever reason

If you don’t know the reason for it not being public, why are you advocating making it public? Or maybe just make a PR making it `public` and see what the devs will say.

---

<div class="post-metadata">

**Author:** ![DanielVandH](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielvandh/32/31134_2.png) [@DanielVandH](https://discourse.julialang.org/u/DanielVandH)\
**Post date:** [September 28, 2024, 4:27pm UTC](https://discourse.julialang.org/t/ref-is-not-a-concrete-type-poorly-documented/120375/12 "2024-09-28T16:27:36Z")

</div>

I’ve already made the thread linked in my first reply? By “for whatever reason” maybe replace it with a bizarre reason - see the linked thread.

---

<div class="post-metadata">

**Author:** ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)\
**Post date:** [September 28, 2024, 7:51pm UTC](https://discourse.julialang.org/t/ref-is-not-a-concrete-type-poorly-documented/120375/13 "2024-09-28T19:51:53Z")

</div>

Would there be anything wrong with this?

```julia
struct Foo{R<:Ref}
    a::R
end

```

Whenever I care about type stability, I just parameterize my structs and have the compiler figure out the types it needs.

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [September 28, 2024, 9:17pm UTC](https://discourse.julialang.org/t/ref-is-not-a-concrete-type-poorly-documented/120375/14 "2024-09-28T21:17:06Z")

</div>

> [@johnomotani](#):
>
> ```julia
> mutable struct BazSubStruct
> b::Int64
> end
> struct Baz
> a::BazSubStruct
> end
> 
> ```
> 
> ?
> 
> That seems like quite a bit of boiler-plate code, which I’d only bother with if it was performance critical…

Here’s the definition of `RefValue`, from  
[https://github.com/JuliaLang/julia/blob/master/base/refvalue.jl:](https://github.com/JuliaLang/julia/blob/master/base/refvalue.jl:)

```julia
mutable struct RefValue{T} <: Ref{T}
    x::T
    RefValue{T}() where {T} = new()
    RefValue{T}(x) where {T} = new(x)
end
RefValue(x::T) where {T} = RefValue{T}(x)

```

…so I’d be surprised if the manual boilerplate version has any performance benefits

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [September 28, 2024, 9:22pm UTC](https://discourse.julialang.org/t/ref-is-not-a-concrete-type-poorly-documented/120375/15 "2024-09-28T21:22:50Z")

</div>

My guess is @jameson’s performance claim in the github issue was comparing RefValue wrapped in a struct to using a mutable struct directly. I’d be interested in better understanding why that is and the tradeoffs here. Specifically, let’s consider a wrapper to count function calls, as used in various packages for optimization, quadrature, et cetera. There are two obvious implementations:

```julia
struct Count{F}
    f::F
    count::Base.RefValue{Int}
    Count(f::F) where {F} = new{F}(f, Ref(0))
end
(c::Count)(args...) = (c.count[] += 1; c.f(args...))

```

or

```julia
mutable struct Count{F}
    const f::F
    count::Int
    Count(f::F) where {F} = new{F}(f, 0)
end
(c::Count)(args...) = (c.count += 1; c.f(args...))

```

Can anyone enlighten me as to the performance characteristics and tradeoffs of these alternatives?

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [September 28, 2024, 9:32pm UTC](https://discourse.julialang.org/t/ref-is-not-a-concrete-type-poorly-documented/120375/16 "2024-09-28T21:32:54Z")

</div>

Why isn’t `Ref` an `AbstractRef` and `RefValue` the go-to `Ref` anyway? It seems odd to be primarily instantiating the `RefValue` type with its supertype per the docstring, like habitually using `AbstractFloat` to make `Float64` values. `Ref` has other subtypes and its constructor doesn’t always make a `RefValue` even among unary methods.

```julia
julia> subtypes(Ref)
6-element Vector{Any}:
 Base.CFunction
 Base.RefArray
 Base.RefValue
 Core.Compiler.RefValue
 Core.LLVMPtr
 Ptr

```

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [September 28, 2024, 11:09pm UTC](https://discourse.julialang.org/t/ref-is-not-a-concrete-type-poorly-documented/120375/17 "2024-09-28T23:09:46Z")

</div>

> [@Benny](#):
>
> Why isn’t `Ref` an `AbstractRef` and `RefValue` the go-to `Ref` anyway?

this 💯 . I guess the practical answer is it’s too late to change anything.

IIUC, the current behavior is as if `AbstractVector{Any}()` would return `Any[]`, doesn’t make much sense with respect to other parts of Julia

---

<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, 10:18am UTC](https://discourse.julialang.org/t/ref-is-not-a-concrete-type-poorly-documented/120375/18 "2025-04-12T10:18:08Z")

</div>

> [@nsajko](#):
>
> Then put it in a package and register it.

Done:

> [@\[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…
