I found myself often using the quite uncomfortable
fieldnames(typeof(x))
Searching for something unrelated, I found in an old thread this magic:
propertynames(x)
Which turns out to be a fantastic alternative without so much boilerplate, and also the recommended way to override fieldnames functionality for those situations in which you want to keep attributes private, etc. The thing is, this is poorly documented.
only shows up in one “important” page, Essentials, which is the least self-explanatory source of information, because it is just a collection of Base
Final discussion
However, there is a more important point to make here, further than achieving more coverage for propertynames (quote for emphasis):
Properly documenting the distinction between properties and fields.
Several programming patterns depend upon exposing some fields of an struct and hiding others, or discouraging direct access to struct fields and rather use “getters”/“setters” (or any ad hoc method). This is the nature of the difference between fields and properties, and should be explained somewhere.
Final question
Can I propose a PR? Will it be welcome? Is this just me?
Yes, absolutely! Documentation PRs are always very welcome, especially from users who may be fairly new to Julia, since it’s often difficult to judge for contributors which parts new users struggle with the most and where our documentation could still be improved.
Yes, better documentation would be great, and especially the intent of properties could be explained more. And yes, the distinction should be documented, and I currently fail to understand it. I thought of properties as an abstraction of fields, allowing for exposing and hiding things, and providing a property interface where the underlying fields could be changed without breaking behavior or the user knowing. However, the abstraction doesn’t always make sense:
getfield and getproperty are roughly parallel, but not so for fieldnames and propertynames. Years ago you could do fieldnames(dog) but that was deprecated for reasons I don’t recall. But why should it be fine to do propertynames(dog), and why does propertynames(typeof(dog)) do what it does? That would be helpful to have explained in the documentation.
This is because properties may vary across instances of a given type, contrary to fields which appear in the type definition. For example, DataFrame columns can be accessed using getproperty, and column names of course vary from one data frame to another.
Indeed, properties are a pretty good abstraction, and I prefer propertynames(dog) anyway. I guess the leakier abstraction was with fields, hence fieldnames(typeof(dog)). So @nandoconde, perhaps the appropriate thing is flip the emphasis: propertynames could be referenced 8 times, and fieldnames only 4! Thanks for raising the point, I think this is well worth improving.