Return statements and global consts in a struct

I posted this on Slack, but looking for some detailed answers. I recently saw a code snippet in Julia

struct _GLOBAL_RNG <: AbstractRNG
    global const GLOBAL_RNG = _GLOBAL_RNG.instance
end

Jeff described this as basically defining a global const, but doing it inside a struct suppresses the default constructor. Mason replied that this is equivalent (it’s not)

struct _GLOBAL_RNG <: AbstractRNG
    return nothing
end
const GLOBAL_RNG = _GLOBAL_RNG.instance

but here we see a return statement in a struct.

What are the reasons for this? How come the default constructor is not needed and how come we can put a return statement inside a struct?

2 Likes

How is it not equivalent, what’s the difference?

Anyway, I’m not acquainted with Julia’s internals, but maybe this helps somewhat:

julia> struct S
               return nothing
       end

julia> S() # The default constructor
ERROR: MethodError: no method matching S()
Stacktrace:
 [1] top-level scope at REPL[2]:1
 [2] run_repl(::REPL.AbstractREPL, ::Any) at /build/julia/src/julia1.5.4/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:288
1 Like

I also ran into this, see here:

3 Likes

Or maybe it is. I am not sure. Just trying to get an overview of what is happening here.

This trick is also used with missing, see here.

"""
    Missing
A type with no fields whose singleton instance [`missing`](@ref) is used
to represent missing values.
"""
struct Missing end

"""
    missing
The singleton instance of type [`Missing`](@ref) representing a missing value.
"""
const missing = Missing()
1 Like

I think this is slightly different right? This actually sets up a default constuctor. Jeff, on Slack, said there are some uses to not have a default constructor as well. For example, in my original code, you’d want to prevent people from writing out _GLOBAL_RNG()p as it can be misunderstood as setting up a new RNG.