On Wednesday, 4 February 2015 18:30:06 UTC, Josh Langsfeld wrote:
>
> I'm very much enjoying thinking about this and considering what might be
> the most Julian approach
>
> > I thought one problem with not having "proper" inheritance is that this
> doesn't really help? Even small variations across AbstractAtoms types
> require a full implementation?
>
> Actually, I don't think there's any substantial difference with Julia's
> inheritance model. Because if the concrete types share field names, methods
> can still access those fields even when they only know they have an
> abstract type. And if the fields are different, then any inheritance model
> would require a new implementation. The only difference is that in the case
> of same-name fields, the declarations must be repeated for each concrete
> type, which a fairly mild tax given that a macro can do it easily.
>
If I read this correctly, then what you are saying is that I am allowed to
assume that my concrete abstract subtypes will contain certain fields, and
if they don't then too bad for them, they need to go and re-implement some
of the structure that I provide for AbstractAtoms.
> This was my initial thought as well. The problem with that is that the
> Atom and Calculator, NeighbourList and Preconditioner objects are "linked":
> when Atoms is updated, then a "message" is sent to Calculator,
> Preconditioner and NeighbourList so that they can update themselves also.
> The Calculator, NeighbourList and Preconditioner objects in fact store
> additional data that is dependent on the data stored in Atoms.
>
> > Because the same issues arise for NeighbourLists, for Preconditioners
> and potentially other objects that will be linked to Atoms type objects.
>
> If you don't even know which objects will be linked when get_forces is
> first called, then I don't think you have any choice but to dispatch twice.
> First on the type of atoms, and second on the type of the internal
> variables, just as you did in your Option 1 code. But I think you can avoid
> the clunkiness by being a bit more fastidious about defining an interface
> for AbstractCalculator, AbstractPreConditioner, etc... and use those
> interface methods instead of just forwarding everything to a more
> specialized version of get_forces. That is, you might have something like
> getparam1(::AbstractCalculator) and then get_forces can directly send it
> a.calc without worrying exactly what type it is. But if the other object
> implementations are so different that no interface is possible, then yeah,
> I think you just have to write a different method for each possible
> combination of types.
>
How about this then; in this case a new AbstractAtoms sub-type or a new
AbstractCalculator sub-type would not need to implement the "interface"
get_forces(a), but only the get_forces(a, c).
type Atoms <: AbstractAtoms
X
calc
neigs
precon
end
get_forces(a::AbstractAtoms) = get_forces(a, a.calc)
or even, as Avik Sengupta suggests, if an AbstractCalculator `c` has a
field c.atoms, with a.calc.atoms == a, then I could even call
get_forces(a::AbstractAtoms) = get_forces(a.calc)
function get_forces(a::AbstractAtoms, c::AbstractCalculator)
ta = typeof(a); tc = typeof(c)
error("get_forces(::$ta, ::$tc) has not been implemented")
end
Thanks, I really appreciate this discussion.
Christoph