Support for other package without requiring it


#1

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?


#2

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


#3

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


#4

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!


#5

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


#6

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


#7

Err… I dunno. Does that work?


#8

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.


#9

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.


#10

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


#11

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)


#12

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