Is it possible to override keyword arguments for specific types?

I have library code that looks like the following:

foo(x) = 1
foo(::Float64) = 2.0
foo2(x; height=foo(x)) = "hi"

and I want to override foo2 in the special case where foo(x) returns a MyType. Looking at https://docs.julialang.org/en/stable/devdocs/functions/#Keyword-arguments-1 it seems like it should be possible if I can get access to the autogenerated function #foo2#1. Is this possible?

For context, the actual function is Base.show_delim_array and I’m trying to override it in the case that l=last(LinearIndices(itr)) is of type Infinity from InfiniteArrays.jl. This seems like the easiest way of preventing show(stdout, 1:∞) from printing forever. Of course, I can override this for special array types, but this has limitations for “composed arrays” like view(1:∞, 3:∞).

I know this is a “bad” idea, but I view it as a temporary work around until I can make a PR to Base to give me the right overloading abilities.

I don’t think you can dispatch on keyword argument types.

I’ve also encountered this issue with the keyword argument frenzy that happened in 0.7. Previously I could just overload a function by specifying the argument type but then it got moved to a keyword and it is no longer possible.

1 Like

That’s unfortunate. Though note it is possible to override as long as keywords are explicitly stated:

julia> foo(;height=1) = "hi"
foo (generic function with 1 method)

julia> (::Core.kwftype(typeof(foo)))(::NamedTuple{(:height,),Tuple{Float64}}, ::typeof(foo)) = "bye"

julia> foo()
"hi"

julia> foo(height=3)
"hi"

julia> foo(height=3.0)
"bye"

Maybe a function analogous to Core.kwftype could be added?

You actually can dispatch on keyword arguments now…sort of. The syntax is kind of awkward, but I noticed that Base does this for things like mapfoldl: https://github.com/JuliaLang/julia/blob/09bfc83f724874af2d7eefe925436848c7b1038f/base/reduce.jl#L37

2 Likes

That requires the function being designed to allow it, right? So I wouldn’t be able to override an existing function like Base.show_delim_array?

Right, it only works if there’s a generic “catchall” version of the function that grabs up the keyword arguments and then calls some inner function with kw.data.

Do you know if there is a way to use this trick for multiple keyword arguments without dispatch caring about the order?

julia> NamedTuple{(:a, :b)} <: NamedTuple{(:b, :a)}
false

Whoops: show_delim_array has default arguments, not keyword arguments, so easy to override.