How to interpret this function with no name, and two sets of parenthesis

Can anyone help me understand how to interpret the below function?

It appears to be an anonymous function, but has two sets of parenthesis.

function (j::JSON)(io, args)

(io, args) are arguments to this function. But what does (j::JSON) mean? How should I interpret this?

function (j::JSON)(io, args)
    if j.recursive
        logmsg = to_namedtuple(Any, args; nest_kwargs=j.nest_kwargs)
        try
            JSON3.write(io, logmsg)
        catch e
            if j.nest_kwargs
                fallback_msg = to_namedtuple(String, args; nest_kwargs=true)
                fallback_msg.kwargs["LoggingFormats.FormatError"] = sprint(showerror, e)
            else
                fallback_msg = (; to_namedtuple(String, args; nest_kwargs=false)..., Symbol("LoggingFormats.FormatError") => sprint(showerror, e))
            end
            JSON3.write(io, fallback_msg)
        end
    else
        logmsg = to_namedtuple(String, args; nest_kwargs=j.nest_kwargs)
        JSON3.write(io, logmsg)
    end
    println(io)
    return nothing
end

This function comes from the LoggingFormats.jl package.

It can be found here:

1 Like

Those are methods for function-like objects. The method table belongs to the objects’ type. In this case, j is a callable instance of JSON; that’s a name so this is not anonymous.

Typical functions are in fact also function-like objects, they just automatically get additional properties like having singleton types (no fields), a const name for the sole instance, subtyping Function for all the methods and heuristics with it, and some printing changes. You can also add methods to a typical function like function (::typeof(foo))(args...) end, it’s just way less convenient.

4 Likes

MWE:

julia> struct A x end

julia> (a::A)(y) = y * a.x

julia> a = A(2)
A(2)

julia> a(3)
6
2 Likes

Thank you both - very clear