How to avoid function name conflict without using the package identifier every time

Hello everyone,

I was wondering if there was a way to avoid conflicts with a function name between packages without using the package identifier every time. To explain what I mean, when I write the following:

using DataFramesMeta
using ShiftedArrays

rev_df = DataFrame(firm_id = ["A", "A", "A", "A", "B", "B", "B", "B"] , 
	rev = [100, 200, 300, 400, 50, 67, 75, 90],
	yr = [2001,2002,2003,2004,2001,2002,2003,2004])

using IterTools

new_rev_df = @chain rev_df begin 
	groupby(:firm_id)
	@transform :rev_lag = lag(:rev)
end

I get the output:

julia> new_rev_df = @chain rev_df begin 
           groupby(:firm_id)
           @transform :rev_lag = lag(:rev)
       end
WARNING: both IterTools and DataFramesMeta export "groupby"; uses of it in module Main must be qualified
ERROR: UndefVarError: groupby not defined
Stacktrace:
 [1] top-level scope
   @ REPL[5]:2

Now this can be resolved by the following:

new_rev_lag = @chain rev_df begin 
	DataFramesMeta.groupby(:firm_id)
	@transform :rev_lag = lag(:rev)
end

This works because I’ve specified before groupby that I’m calling the function from DataFramesMeta.

My issue is, in my code I have to use IterTools just once, whereas I have to use DataFramesMeta's groupby() function many, many times. So having to write DataFramesMeta.groupby() every time I want to do a grouping actually ends up being quite tedious.

Is there a way around this? The simplest I could think of was to load IterTools when I need it, then “unload” the package so that there’s no conflict when the DataFramesMeta's groupby() function needs to be used. As far as I can tell, Julia doesn’t let the user unload a package like this, although I might be missing something.

I’d appreciate some sort of workaround that anyone is aware of. Thanks!

You could also import only the one method from IterTools that you need, with something like

using DataFramesMeta
using IterTools: chain

See Modules · The Julia Language for why that works

10 Likes

Putting a line like this should help:

const groupby = DataFramesMeta.groupby

Here is a completely reproducible example which does not require 3rd-party packages:

julia> module Foo
       export groupby
       groupby() = "Foo.groupby"
       end
Main.Foo

julia> module Bar
       export groupby
       groupby() = "Bar.groupby"
       end
Main.Bar

julia> using .Foo

julia> using .Bar

julia> groupby()
WARNING: both Bar and Foo export "groupby"; uses of it in module Main must be qualified
ERROR: UndefVarError: groupby not defined
Stacktrace:
 [1] top-level scope
   @ REPL[5]:1
julia> const groupby = Bar.groupby
groupby (generic function with 1 method)

julia> groupby()
"Bar.groupby"
6 Likes

This works, thanks.

EDITED: To be accurate, I need to do this:

using IterTools: product
product(rev_df.rev, rev_df.yr)

If instead I did this:

using IterTools: product 
IterTools.product(rev_df.rev, rev_df.yr)

then I get the following error:

julia> IterTools.product(rev_df.rev, rev_df.yr)
ERROR: UndefVarError: IterTools not defined
Stacktrace:
 [1] top-level scope
   @ REPL[6]:1

In both of the above cases the conflict with DataFramesMeta.groupby goes away, but in the former case I can use IterTools.product() as well.

This works as well, thanks!

There is the import X as Y syntax, personally I think this is a great but underused feature. You could replace using IterTools by import IterTools as IT and then use IT.product etc.

3 Likes

Which version of Julia introduced this? I believe 1.5 and below do not support it.

The using X: y has imo some unintuitive behavior. using DataFrames: groupby brings groupby into Main but not DataFrames. This is a useful stopgap is module names conflict with other names.

julia> using DataFrames: groupby;

julia> groupby
groupby (generic function with 1 method)

julia> DataFrames
ERROR: UndefVarError: DataFrames not defined
2 Likes

I think so. For older julia versions I recommend the pattern import IterTools; const IT=IterTools.

1 Like

Ah okay makes sense. That’s why IterTools.product() was throwing an error about how IterTools wasn’t defined, but using product() worked fine.

1 Like

This should also work

using DataFrameMeta
groupby
using IterTools

Now groupby is the one from DataFramesMeta.

1 Like