Each time I implement a new getproperty method for a structure I found myself filling the code with lengthy (and sometimes nested) calls to getfield. So far the best looking solution I came up with is:
⋄ = getfield # type \diamond<TAB>
It also has a relatively high precedence with respect to other operators.
MWE:
import Base.getproperty
⋄ = getfield
struct MyStruct
greet::String
end
function getproperty(s::MyStruct, name::Symbol)
@info "Accessing the $name property"
s ⋄ name # in place of the longer `getfield(s, name)`
end
s = MyStruct("Hi")
s.greet * " there!"
s⋄:greet * " there!" # correct operator precedence
Is there any other recommended, or widely used syntactic sugar for getfield ?
Its still nice to define these methods if you don’t want the user to use the fields directly. DataFrames defines getproperty to work with columns but then also has internal methods for accessing the actual fields of a data frame.
I’m not certain, but my initial thought was that @marius311 meant that you can do something like this:
function getproperty(pd::PropertyDict, sym::Symbol)
if sym == :d
getfield(pd, :d)
else
getfield(pd, :d)[sym]
end
end
That pattern can work in some scenarios, but in the case of the PropertyDict above, you want to be able to put any symbol into the dictionary as a key. In other words, you want to allow for the possibility that :d is one of the keys in the dictionary.
It seems like we’re talking past each other here. Take a closer look at my second example. The issue arises when you overload getproperty. Once you do that, you can no longer use dot syntax to access the underlying fields of your struct, so you have to run around calling getfield(a, :x) all the time, which gets messy real fast.
I see that this thread is a bit old (but popped up on the front page now).
But is it really a good idea to let properties and fields share the same names? I see properties as part of the interface, but fieldnames as implementation details, and would think that their names should be decoupled.
And even if you don’t want properties as part of the interface, it seems to me that they should be ‘virtual fields’ that have unique names, separate from the fieldnames.
I’m afraid my initial question was slightly misleading. I’ll try to rephrase as follows:
The default implementation of getproperty is to call getfield, and the dot-syntax is a sugar for getproperty. Hence, in my module implementation, I can access structure fields with struct.fieldname.
Now assume I want to provide a high-level interface(*) by implementing a getproperty method for my structure definitions. All my struct.fieldname statements would no longer works, and I need to explicitly invoke getfield (possibily several times in the same statement, when dealing with nested structures…).
Is there any alternative, commonly adopted, sugar for getfield?
According to above answers, I guess the final answer is “no”.
Which is not necessarily a big deal: ⋄ works for me. It is just aesthetically unpleasant…
(*): e.g. to protect the implementation details and, most importantly, provide access to views over specific fields of multi-level nested structures.
But the key point here is to assume there is a very good reason to overload getproperty (to simplify usage outside my module), while still accessing fields with getfield (within my module).
Answers like “Why do you need that?”, “Do this instead”, etc. are attempts to circumvent this assumption…