Randn types, @which

I am exploring the relationship between a method call, and the particular method chosen. So consider

@which randn(Int64, 3, 4, 2)

which returns

randn(::Type{T}, dims::Integer...) where T in Random at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.3/Random/src/normal.jl:186

First, it would be nice if the link returned corresponded to an existing path on my file system (MacOs 14.x). It does not. Not sure how that is possible.

Second, let us actually call the function:

randn(Int64, 3,4, 2)

I get the error below.

ERROR: MethodError: no method matching randn(::Random.MersenneTwister, ::Type{Int64})
Closest candidates are:
 randn(::Random.AbstractRNG, ::Type{T}, ::Tuple{Vararg{Int64,N}} where N) where T at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.3/Random/src/normal.jl:181
 randn(::Random.AbstractRNG, ::Type{T}, ::Integer, ::Integer...) where T at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.3/Random/src/normal.jl:184
 randn(::Random.AbstractRNG) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.3/Random/src/normal.jl:39
 ...
Stacktrace:
[1] randn!(::Random.MersenneTwister, ::Array{Int64,3}) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.3/Random/src/normal.jl:173
[2] randn at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.3/Random/src/normal.jl:184 [inlined]
[3] randn(::Type{Int64}, ::Int64, ::Int64, ::Int64) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.3/Random/src/normal.jl:186
[4] top-level scope at none:0

Given the error, why does the function

randn(::Type{T}, dims::Integer...) where T 

exist? Doesn’t the three dot operator signify an arbitrary number of integers? If the function call only works for two integers, why not create a specialized type to that effect.The only answer I have is that the function accepts one or two integers as arguments, and the … was the easy way to accomplish this.

That method simply calls through to randn(Random.default_rng(), T, dims...).

It is the latter function that is not implemented for T == Int64. Hence the MethodError for randn(::Random.MersenneTwister, ...) (note the first argument, which is an RNG object).

This is a pretty common pattern: a generic higher-level wrapper calls through to a lower-level function that actually implements the computation. That way, if you want to implement randn for a new type T, you only need to implement the lower-level method and you get the higher-level methods for free (since they are type-generic). The downside of this approach is that, for unimplemented methods, the MethodError is thrown from the lower-level function rather than the function that the top-level user is calling.

4 Likes

The file path is cached when Julia is built which is why it shows that path. However, on 1.4 this should be fixed.

2 Likes