Unsure about properties

I like the syntax of properties, like that they’re not the same as fields, and that I don’t have to export them. I’m considering switching from using accessor functions to properties in a large chunk of code, but I’m not sure it’s a good idea.

Suppose I have struct S end.

  1. Is it okay to use underscores as property names? S()._ is currently valid syntax.

  2. Should we be allowed to define properties for Type{S}? This would be useful in, for example, accessing parameters in parametric types (like Array{Int64, 2}.dims). Currently, I can define S._ by overwriting Base.getproperty. The issue is, types already come with these property names (:name, :super, :parameters, :types, :instance, :layout, :hash, :flags) and I don’t know that it’s gaurenteed that they will not change in the future. I don’t think I can redefine Base.getproperty from inside another funtion, so I would need a macro? I’d need to make sure that the existing names don’t conflict the user-defined names. But then also make sure that I’m able to update the definition of properties that I myself defined.

  3. What if I redefine S.name?

  4. If I should be allowed to define properties of types (S._), what’s a good way to update Base.propertynames?

  5. What happens if I don’t update propertynames? I figure it’s a good way to keep track of what properties a type or its subtypes is supposed to implement. Which brings me to:

  6. What’s a good way to verify that a list of properties have been implemented for a type? This is my current approach:

Base.getproperty(s::S, name::Symbol) = getproperty(s, Val(name))       # dispatch on Val{name}
Base.getproperty(s, ::Val{name}) where {name} = Base.getfield(s, name) # default: pass to getfield
Base.getproperty(s, ::Val{:_}) = "underscore" 						   # define property
hasmethod(getproperty, Tuple{S, Val{:_}}) 							   # verify: do this for all properties
  1. What are other things to consider when choosing between (accessor) functions and properties?