How to not import Base.isopen

I would like to write my own isopen function and therefore not import Base.isopen. I have thought of two ways to do this:

module MyModule
function isopen end

# Lots of code...
include("file_that_defines_isopen.jl")

end

and

baremodule MyModule
import Base: Base, include, @__MODULE__, foreach, filter, names, Meta, βˆ‰
eval(x) = Core.eval(@__MODULE__, x)
include(x) = include(@__MODULE__, x)
foreach(x->eval(Meta.parse("import Base: $x")), filter(βˆ‰([:isopen]), names(Base)))

# Lots of code...
include("file_that_defines_isopen.jl")

end

Even though the first version is shorter, I still prefer the clarity of the second version, but unfortunately it fails for symbols like '. Is there a way to get the second version to work or is there a third version that is even better?

I finally got it to work with the following code:

baremodule MyModule

import Base: Base, @eval, @__MODULE__, foreach, filter, names, βˆ‰
eval(x) = Core.eval(@__MODULE__, x)
include(x) = Base.include(@__MODULE__, x)
foreach(filter(βˆ‰([:isopen]), names(Base))) do sym
    @eval import Base: $(sym)
end

# Lots of code...
include("file_that_defines_isopen.jl")

end

I think it would be better to utilize multiple dispatch, i.e. to define your own type and define your own version of isopen for it.

2 Likes

In my case, I feel that this would be punning. The docstring for isopen seems to be intended for streams and things like that. In my case, I want to use it for querying if a market was open at a specific time. I feel that these two uses are so different that I do not wish to just make another method for Base.isopen, but rather make a MyPackage.isopen function. By not importing it, I am doing what I can to avoid confusion without having to use another name. I do also require using my own type as one of the arguments, so erroneous use should throw an exception.

Then maybe it is better to use a much explicit name to avoid any confusion, such as ismarketopen.

2 Likes

I think it’s fairly common to just have your function public but not exported, so that isopen is for streams and MyPackage.isopen is for your type.

Of the two approaches in the original post, the first seems much more idiomatic to me and also much safer. What was the issue with the first approach?

A huge hazard of importing all the methods in Base is that any function you define that happens to coincide with an imported Base function (in this case every public function, of which there are currently more than 1000) will add a method to the Base version instead of defining a new function (because an explicitly imported function does not require namespace qualification to extend). And note that more public functions will be added to Base in the future. Which means at any point in the future (if not present), you might accidentally pirate Base functions and break something in a hilarious or not-so-hilarious way.

1 Like