-
Notifications
You must be signed in to change notification settings - Fork 83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
multiple packages using a type of file? #46
Comments
FileIO allows to register multiple libraries for one format. This is how you can register multiple libraries for one file format: Best, |
This is also an issue for me. In my case, I am writing a package to deal with PLY files in a way different than MeshIO.jl My suggestion is that perhaps FileIO.jl can have some
|
Can you explain what your package is doing differently? Would it make sense to generally prefer it to the one in MeshIO? If you like, you can supply a pull request for this! Should be quite straight forward to first search for already included modules in the IO list in https://github.com/JuliaIO/FileIO.jl/blob/master/src/loadsave.jl#L75 |
My package builds Julia types to correspond directly to whatever is I haven't implemented binary format IO yet so that's why I haven't
|
Oh, hmm, well this is somewhat embarrassing, but I also implemented a ply IO library (https://github.com/FugroRoames/PlyIO.jl) and came to FileIO to discuss exactly the same issue! It's an interesting one, because MeshIO and PlyIO have quite different views on what the user wants from loading a ply file: PlyIO models ply as a generic container of arbitrarily named elements and properties (essentially what you see in the header), while MeshIO wants a fixed format, and will interpret that as a mesh for you. Unfortunately, it's not really possible to guess which one of these the user will actually want, because they'll want different things in different contexts. I think this requires an extension of the using MeshIO
using PlyIO
a_mesh = load(AbstractMesh, "test.ply")
a_ply = load(Ply, "test.ply")
a_something = load("test.ply") # Fall back to the current precedence system; I guess FileIO will need to guess what people want "most of the time"... A generic fallback is straightforward: load{T}(::Type{T}, args...; kwargs...) = load(args...; kwargs...) |
Perhaps the generic fallback could be a bit smarter, to avoid some of the issues with load{T}(::Type{T}, args...; kwargs...) = load(supertype(T), args...; kwargs...)
load(::Type{Any}, args...; kwargs...) = load(args...; kwargs...) |
Hm, I'm not a 100% sure if the type you want should influence the loader library. In fact, I'm using load in a very similar way, but defined as something like: load(T, args...) = convert(T, load(args...)) I'd argue, that you might want this behavior, since you still want a way to enforce type stability even when loaders switch under the hood. load{T}(M::Module, args...; kwargs...) = M.load(args...; kwargs...)
load(file, args...; kwargs...) = load(figure_out_module(file), args...; kwargs...) |
The module version is interesting, but I don't think it solves the whole problem: Requiring the user to mention the backend loader module has the wrong semantics from a library user's point of view. If I'm loading data from a file, I primarily care about which type of things I can do with the resulting data object. On the other hand, I don't care so much about which module was involved in the loading. Achieving this abstraction of "just go find a good library to load this" seems to be the whole problem that Let's consider: loading images vs arrays. These two types of objects are quite similar in many ways, with a somewhat interchangeable data model. However, they're not quite the same. I'd like to be able to achieve the equivalent of the following with FileIO: filename = "whatever.blah"
an_image = load_image(filename)
an_array = load_array(filename) Semantically, I now know that So, how do we achieve this? It's tricky right? In fact it seems to be a kind of multiple dispatch. We have as input:
Putting these two things together, So, with all that in mind, I think I'd like to be able to write: filename = "whatever.csv"
an_image = load(Image, filename)
a_matrix = load(Matrix, filename) With this kind of design, it seems like individual packages can't directly overload the |
Why not use, say, |
You mean return type? |
The loader of |
hm... but return type and loader library are not strictly coupled! |
I see (well not quite), in that case that does not work. |
That's especially the case for png's, where all IO libraries only return Arrays on the lower level, but then get conveniently converted to an Image. Also, asserting that you get |
So, after almost 6 years this still has not been solved (and yes, I just did write yet another A way to ease the dispatch would be to let the user decide which package gets the This could be implemented by e.g. exposing a couple of functions, If a conflict exists, the only reasonable way to solve it is by hand (since only the end-user knows which type they really want, etc.); a possible API for it is letting any package with two conflicting dependencies call e.g. The final result for this is that the end-user, when they load only non-conflicting packages, still has a nice (Final small bonus: dispensing with global registry kills the chicken-and-egg problem of #124) |
We have several packages that might handle a specific type of file (and will return an object based on those file's contents). Does the presence of the centralized registry mean that only one package can "register" a dependency for that type of file for use in FileIO?
To use an existing example, it looks like PNG requires ImageMagick. But if I'm working on my own package that uses PNGs, and don't use ImageMagick myself in my package, does this mean that if I want to use FileIO for loading PNGs, I'm stuck with requiring my users to download (if not use) ImageMagick?
Sorry for the basic questions. My use case is with graph and matrix file formats, and there are many packages out there that use them in completely different ways.
The text was updated successfully, but these errors were encountered: