Extending function from Base

The function Base.binomial(n, k) has 3 different calling patterns:

julia> methods(Base.binomial)
# 3 methods for generic function "binomial":
[1] binomial(n::BigInt, k::UInt64) in Base.GMP at gmp.jl:641
[2] binomial(n::BigInt, k::Integer) in Base.GMP at gmp.jl:642
[3] binomial(n::T, k::T) where T<:Integer in Base at intfuncs.jl:933

I implemented an extension to real/complex arguments in a module SpecialFunctions:

binomial(x::Number, y::Number) = inv((x+1) * beta(x-y+1, y+1))

My problem now is that after using SpecialFunctions in REPL I explictly need to say which binomial I want to call.

julia> using SpecialFunctions
julia> binomial(1,1)
WARNING: both SpecialFunctions and Base export "binomial"; uses of it in module Main must be qualified
ERROR: UndefVarError: binomial not defined
Stacktrace:
 [1] top-level scope at REPL[1]:1
 [2] run_repl(::REPL.AbstractREPL, ::Any) at /build/julia/src/julia-1.5.3/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:288
julia> Base.binomial(1,1)
1
julia> SpecialFunctions.binomial(1,1)
1.0

How should I define SpecialFunctions.binomial such that Base.binomial is still called by default if the arguments make it possible, e.g. Integer arguments?

Presumably this is in reference to SpecialFunctions.jl#293. If you want to extend a Base method (defined only for integers) with a more general method for other number types, you can simply define:

Base.binomial(x::Number, y::Number) = inv((x+1) * beta(x-y+1, y+1))

(I feel like this is explained in the Julia manual, but I can’t find the section?)

(This is type piracy, but might be acceptable here?)

3 Likes

Thanks. Easy solution.

Regarding the type piracy: I don’t see any direct issues. Lets see if anybody voices concerns for the pull request…

Following your solution and extending Base.binomial do we still need to export binomial in the module.
What I mean: In the file SpecialFunctions.jl do we need a line export binomial?

Nope, no need to export. Defining Base.binomial put’s it in base and available to everyone.

1 Like

It is type piracy, but it is a more generic case than the others, consequently, it will only be called unintentionally in situations someone would trigger an error (a MethodError more specifically). Not ideal (can lead to subtle bugs from someone that is programming by try-and-error instead of using documentation) but not broken I think.