There’s a lot of good ideas in this thread, but as far as I can tell they’ve been discussed in more detail in the github issue linked above by @Tamas_Papp, have you read it? Especially the (for me) 127 hidden discussion elements hidden by github are insightful as to how this might look in the future.
There’s also a very long discussion about how to handle those kind of relationships between Rectangle and Square you are talking about and how to solve that problem.
It’s a very insightful (albeit long) read, if I manage to make some time later today I can maybe summarise what I’ve understood from it.
Yes. And even inside the module, I try to use field access as little as possible, just defining a few very primitive functions that do field access, and building everything on top of those. Perhaps even to a slightly excessive degree…
I don’t think this is excessive, it is just good habits.
The only thing preventing me from doing it more is that occasionally I ponder over the merits of naming the accessor thing vs getthing vs get_thingy etc for 10 minutes, which is how I know it is time for a coffee break
If this was possible then you could never store such a type inline, and this is a cost that every type would pay, not just the ones that are actually subtyped. That would severely undermine Julia’s quality and utility for efficient (numerical) computing. In order to avoid this cost, you’d have to get into OOP modifier games with final types or since we’d probably want that to be the default, some kind of nonfinal keyword (ugh), which seems super distasteful. I think having better support for copying a type’s structure and/or methods with modifications seems like a better direction.
In terms of the Rectangle example, I don’t really see why this arrangement is so bad:
abstract type AbstractRectangle{T<:Real} end
struct Rectangle{T<:Real} <: AbstractRectangle{T}
width::T
height::T
end
struct Square{T<:Real} <: AbstractRectangle{T}
side::T
end
Is the objection that you need to have an extra abstract type? That seems like a significant conceptual clarification to me. You can even define square.width and square.height if you want to.
Out of curiosity, is it also idiomatic to define a formal method for the abstract type with no contents so that the reader (of the code) can see what methods are to be defined for concrete types (i.e. for documentation/readability purpose)?
abstract type AbstractRectangle{T} end
width( x::AbstractRectangle ) =
error("width() should be implemented for ", typeof(x))
Not sure. I don’t think it’s common, but it doesn’t sound like a terrible idea. It will anyway show up as a missing method error, though, so it’s perhaps a bit redundant.