-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
StridedArray should be an abstract class, not a union #2345
Comments
See also #987 . |
It would be great to have a whole hierarchy, but we don't need to have it all at once. We can start with |
See also #1276 |
One difficulty here to even experiment is that Once |
No, there might be other StridedArray types like NumPyArray. We might also need a |
Ok. How about getting rid of |
Renaming |
Just thinking if we can reduce one of these things. |
You need at least three types (regardless of what you call them):
As much as possible, our routines should work with the most abstract possible type. For The LAPACK routines should work with In order to avoid the need for explicit transposes in many cases, it might be nice to have a concrete |
add StoredArray and DenseArray to emacs mode
Thoughts triggered by #8235 (comment) reminded me that because Example:
type Image{T,N,A<:AbstractArray} <: AbstractArrary{T,N}
data::A
properties::Dict
end
One can fix it this way: rewrite function somefunction(A::StridedArray, ...)
...
end as somefunction(A::AbstractArray, ...) = _somefunction(A, ..., isstrided(A))
function _somefunction(A, ..., ::Type{TypeConst{true}})
...
end using the definitions isstrided(A::DenseArray) = TypeConst{true}
isstrided{T,N,A<:DenseArray}(A::View{T,N,A}) = TypeConst{true}
isstrided{T,N,A<:DenseArray}(img::Image{T,N,A}) = TypeConst{true}
isstrided(A) = TypeConst{false} It's a little ugly, but perhaps with a Thoughts? |
@timholy, could you expand upon why your images cannot be |
Briefly, our raw data files represent 4d images (3d over time), but they require some computation to be performed upon them before you get out what you'd call an "image". So there's no physical memory address corresponding to a single voxel at a particular time. |
Why would this be a type of |
It's not. But other things that are Images are StridedArrays. The point is that Images as a whole can't be, but certain Images are. |
@timholy Maybe you could create two different types of |
And then how do I share code among the different types of Images? |
Maybe it will be easier to appreciate this if I say it this way: this proposal is a traits-based alternative to multiple inheritance, something people have been wanting in Julia for a long time. In some ways it's nicer, because I don't have to create specialized types that live at the intersection of parents, I can just declare that, based on their parameters, some objects have all the properties of two different types of objects. But this does make me think that a simpler way of achieving this is needed. I wonder if #8154 is worth a second thought? |
By writing generic code for the Your traits idea is interesting, but it would be good to see what other use cases require it. Is it a common pattern? |
The advantages of a traits-based approach is that it scales better. Let's say I have code in Base, package A, and package B that are all useful for my package C. For a "conceptual catagory" I could create 4 types:
but this doesn't scale very nicely, and foists similar headaches on anyone else who wants to create a package D that interacts with my C, and has needs I didn't anticipate. |
@nalimilan, see issue #5. The only single-digit issue left open. Can I close it? Oh, please, let me!! |
@timholy that is really clever. I closed #8154 not because we won't do it, but because I think we will get it in any case from other planned work. Dispatch on values might not even be necessary for this. For example
|
Right, I don't actually care whether the user writes functions that return values or types, and I like your syntax. In cases where it's most likely to be a true/false decision, there might be some value in auto-generating the variant of
EDIT: although I guess you have to worry about what happens with the Another bit of "collateral damage" from this suggestion is that triangular dispatch just drops out, if one wants to allow such crazy syntax:
That said, I 100% agree with you that we also need a way to write triangular types. So if we implement your proposal, this doesn't actually count as an attraction of this one. |
But yes, I'm excited to realize we've had Multiple Inheritance all along, and just didn't recognize it. |
There seems to be a lot of potential for nifty syntactic sugar here. For example
could expand to
|
Ooh, I like that a lot. In generating the expanded version, it clearly denotes what part of the typing should be retained and what part results in extra arguments. Presumably my ColorValue example could turn into
which is much nicer in terms of the signature of the expanded function. |
This trick is really pretty amazing. |
I was intrigued by Tim's trick and implemented a way to do traits/interfaces with it: I think this does indeed implement traits but maybe I missunderstood. @timholy, could you comment? |
I'm not sure I qualify as the arbiter of what counts as "traits" and what does not. Your gist definitely shows off some relevant points, but to the extent that I understand your intentions it seems to have a slightly different thrust at least than how I was thinking of it. My thinking was that traits would generally be defined by a set of functions, and that one application would be to "steer" dispatch to appropriate implementations. There are examples of this idea in the discussion above. To throw another one out there, let's say you want to be able to dispatch on whether an AbstractArray has efficient linear indexing. The "classic" Julia approach might be
You already seem to understand that the big problem with this is that it's not extensible---if I define a new type of The way I think about traits, they are just functions (I'd classify things like
and then write these variants of your function
In contrast to the Union-based approach, this can be extended to a new type simply by defining Jeff's syntax is much more clever than this because he groups the object and its traits together into a tuple. That solves the problem of keeping track of which extra arguments serve as traits for which objects. I don't know if this really answers your question; you may be thinking about a whole new direction. |
@JeffBezanson, out of curiosity, what are your thoughts on the desirability, & timing, of adding sugar for the "traits trick"? I'm asking because I'm mulling over a design issue: in Images, I implemented loading of most grayscale images as an The problem I'm seeing right now is that while Neither path is exactly easy, of course, but that's not the main issue: I'm just wanting to put my effort in the right place. Is this something you're sufficiently interested in that it might happen during 0.4, or is this 0.5, or "never," material? I'd also understand if you're unsure, in which case I'll make up my own mind. |
So far I'm pretty sure I like this better than actual multiple inheritance, and it is much easier to implement as well. It might take a while to get widespread buy-in though. I wouldn't depend on this going in 0.4. |
Sounds reasonable; basically I agree on all counts. Even though it's "trivial," in practice I think it's a pretty big change to how one thinks about types and dispatch in Julia---we might end up re-architecting quite a lot of stuff. Sounds like 0.5/0.6 material to me. |
@timholy, thanks for the comments. I got it all wrong in above gist: https://gist.github.com/mauro3/f3431a24d2737cd932ac But after some more thought I think I got the gist of the trait trick: #6975 (comment) |
Currently, Julia defines
It seems like it would be better to define
and have
Array
andSubArray
both inherit fromStridedArray
.The reason is that I would like to define a new
StridedArray
type (wrapping a NumPyndarray
). There is no reason, as far as I can tell, that I can't provide all the functionality of aSubArray
and be used everywhere the latter is usable, but currently it does not seem possible to do this. Changing toabstract StridedArray
would fix this.The text was updated successfully, but these errors were encountered: