Guidelines to distinguish concrete from abstract types


#1

Is there any proposed guideline to name types and distinguish whether is it a concrete or abstract type?

This would be useful to check whether a package has been developed following this rule: https://docs.julialang.org/en/v1/manual/style-guide/#Avoid-writing-overly-specific-types-1

Besides, a method implementation should not be concerned with the specific implementation of a concrete type. Rather, it should only rely on a specific behaviour of its argument(s), which may be provided by several concrete concrete types sharing a common ancestor type.

I know that several abstract types have a Abstract prefix in their name, hence a correct function signature should be in the form

function foo(arg1::AbstractBar, arg2::AbstractBaz, arg3::AbstractWhatever)

But this looks quite cumbersome to me, I would prefer writing:

function foo(arg1::Bar, arg2::Baz, arg3::Whatever)

and having Concrete as prefix to the concrete type name.

Another possibility would be to propose a (non-mandatory) guideline to prepend or append a single character to all abstract type names.

For instance, I would like to write:

abstract type ∀Bar end
mutable struct Bar <: ∀Bar
  ...
end
function foo(arg1::∀Bar...)

since this reminds me that the foo function works with any of the subtypes of the Bar entity. And is an upside down A (for abstract…) :wink:

However, the character actually lead to a syntax error, hence it is not a viable option.

Any other proposal/comment?


#2

This is not true in general — sometimes you specify a method for a given set of types precisely because to implement it you need to know about the internals. Eg look at the code for +(::Rational, ::Rational).

If you want to dispatch based on the support for an interface, it may be better to use traits instead of abstract types.

I think that enforcing that type names signal their position in the type tree may not be worth it. Eg currently there are many types that do and many that don’t, eg AbstractRange vs Real and Number.


#4

Thanks for the response.

I agree it is not true in general, but it should be so for exported methods in a package since the users (other than the package author) are typically not aware of the detailed implementation.

And of course there are notable examples, like the ones you mentioned, for which this guideline would introduce plenty of breaking changes.

I was just wondering if anyone had the same thought, or if a discussion/agreement were reached in some way.

Besides, the ! convention at the end of functions which modify their arguments is a very convenient approach. So why not extend it to other language aspects?


#5

Ops, I think I misunderstood the guideline in the manual: of course we should avoid being too picky on argument types, but there are cases where a method will only work with a specific implementation, hence it makes sense to require a specific concrete type. This of course applies also to exported methods.

Given my original understanding was wrong, I believe there is no actual strong motivation for the proposal…