View Function Internals within REPL (julian mode)

Hello all.

In R there is an easy way to view what a function does by typing the function name without parenthesis.

> manova
function (...) 
{
    Call <- fcall <- match.call()
    fcall[[1L]] <- quote(stats::aov)
    result <- eval(fcall, parent.frame())
    if (inherits(result, "aovlist")) {
        for (i in seq_along(result)) {
            if (!inherits(result[[i]], "maov")) 
                stop("need multiple responses")
            class(result[[i]]) <- c("manova", oldClass(result[[i]]))
        }
        attr(result, "call") <- Call
    }
    else {
        if (!inherits(result, "maov")) 
            stop("need multiple responses")
        class(result) <- c("manova", oldClass(result))
        result$call <- Call
    }
    result
}
<bytecode: 0x12903cec0>
<environment: namespace:stats>

Is there a similar way to do this in Juila? I know if a function is typed by itself, it gives information about it, but not the internal workings of the function.

julia> using Statistics

julia> mean
mean (generic function with 6 methods)

In Julia, the only methods I know of viewing the internals of a function is by looking at the code repository or running the methods() and looking at the contents of the listed files.

julia> methods(mean)
# 6 methods for generic function "mean":
[1] mean(r::AbstractRange{<:Real}) in Statistics at /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Statistics/src/Statistics.jl:185
[2] mean(a::NamedArrays.NamedArray{T, N}; dims) where {T, N} in NamedArrays at /Users/user/.julia/packages/NamedArrays/TuJLn/src/changingnames.jl:16
[3] mean(A::AbstractArray; dims) in Statistics at /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Statistics/src/Statistics.jl:164
[4] mean(itr) in Statistics at /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Statistics/src/Statistics.jl:44
[5] mean(f, A::AbstractArray; dims) in Statistics at /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Statistics/src/Statistics.jl:104
[6] mean(f, itr) in Statistics at /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Statistics/src/Statistics.jl:61

Is there a way of brining up the function contents within julian mode?

Thank you for your help and time.

The @less macro will do that.

4 Likes

See also the cousins @which, @edit

3 Likes

Thank you both for the answers. This method isn’t quite the same as printing the contents within the REPL (similar to R) but, they get the job done very well. It took me a sec to understand that you run the macro on the function with the type of data being passed into the function. An example of how they work:

julia> methods(mean)
# 5 methods for generic function "mean":
[1] mean(r::AbstractRange{<:Real}) in Statistics at /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Statistics/src/Statistics.jl:185
[2] mean(A::AbstractArray; dims) in Statistics at /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Statistics/src/Statistics.jl:164
[3] mean(itr) in Statistics at /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Statistics/src/Statistics.jl:44
[4] mean(f, A::AbstractArray; dims) in Statistics at /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Statistics/src/Statistics.jl:104
[5] mean(f, itr) in Statistics at /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Statistics/src/Statistics.jl:61

julia> @which mean([1,2,3,4,5]) # This brings up which method is being called.

mean(A::AbstractArray; dims) in Statistics at /Applications/Julia-1.7.app/Contents/Resources/julia/share/julia/stdlib/v1.7/Statistics/src/Statistics.jl:164

julia> @less mean([1,2,3,4,5]) #brings up a less window showing the file contents at the function location.

Top content of the less window

mean(A::AbstractArray; dims=:) = _mean(identity, A, dims)

_mean_promote(x::T, y::S) where {T,S} = convert(promote_type(T, S), y)

# ::Dims is there to force specializing on Colon (as it is a Function)
function _mean(f, A::AbstractArray, dims::Dims=:) where Dims
    isempty(A) && return sum(f, A, dims=dims)/0
    if dims === (:)
        n = length(A)
    else
        n = mapreduce(i -> size(A, i), *, unique(dims); init=1)
    end
    x1 = f(first(A)) / 1
    result = sum(x -> _mean_promote(x1, f(x)), A, dims=dims)
    if dims === (:)
        return result / n
    else
        return result ./= n
    end
end

Thank you again!