Support for other package without requiring it

Is there a way to provide support for the types from another package without actually requiring that package? For example, say I wanted to make the following type in my package:

struct Foo{T<:Real} <: AbstractArray{T,2}
    table::Array{T,2}
    samples::Vector{S} where S
    features::Vector{R} where R
end

I’d like users of my package to be able to make a Foo from a DataFrame if they want to:

function Foo(df::DataFrame)
    return Foo(
            Matrix(df[:,2:end]),
            names(df[2:end]),
            Vector(df[1]))
end

… but I don’t actually need DataFrames for anything else. Is there any way to do this without requiring DataFrames as a dependency and having using DataFrames in my module file?

Requires.jl should work, if you’re willing to sub one dependency for another.

You could create a third package for the functionality that involves Foo and DataFrame.

I think this will work, thanks!

For completeness, that means in my example above I’d do:

using Requires

struct Foo{T<:Real} <: AbstractArray{T,2}
    table::Array{T,2}
    samples::Vector{S} where S
    features::Vector{R} where R
end

@require DataFrames function Foo(df::DataFrame)
    return AbundanceTable(
            Matrix(df[:,2:end]),
            names(df[2:end]),
            Vector(df[1]))
end

Is that right? I’ll give it a shot!

2 Likes

Some plan for glue modules is described on github. That issue is put on the 1.0 milestone.

1 Like

Unrelated question: would it be better to write those as: Vector{<:Any}?

1 Like

Err… I dunno. Does that work?

Yep, it was a nice little bit of syntactic sugar (I think @-stevengj added it), very useful in cases where you don’t need to use the type variable.

1 Like

Is there a way to declare a type without defining it? So I can refer to its name in method definitions, implying that I support this type if someone else defines it. This would allow me to support types defined in other packages without requiring those packages.

Use an abstract type defined in a Base package. That’s why this architecture is used.

That doesn’t work if the type defined in the other package does not inherit from an abstract in Base (other than Any, but that loses specificity)

That is why you require a small Base package as the common dependency.