# Syntactical sugar for `getfield`

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` ?

2 Likes

For an immutable struct, I’ve used this pattern:

``````struct A
x::Int
d::Dict{Int,Int}
end

x(a::A) = getfield(a, :x)
d(a::A) = getfield(a, :d)
``````
``````julia> a = A(42, Dict(1 => 2, 3 => 4))
A(42, Dict(3 => 4,1 => 2))

julia> x(a)
42

julia> d(a) = 6
6

julia> d(a)
Dict{Int64,Int64} with 3 entries:
3 => 4
5 => 6
1 => 2
``````

Note that with this pattern it is still pretty easy to mutate the contents of the dictionary.

Is there a reason not to just overload `getproperty` and then use the normal `.` syntax?

1 Like

@marius311 I’m not quite sure what you mean by that. Can you give an example?

that would be preferred as

The syntax a.b calls getproperty(a, :b).

``````julia> struct A
x::Int
d::Dict{Int,Int}
end

julia> a = A(5, Dict([1=>2, 2=>3]))
A(5, Dict(2 => 3, 1 => 2))

julia> a.x
5

julia> a.d
3
``````

Clearly in my brief example I left out the part where I overload `getproperty`

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.

1 Like

I agree. Often, I use e.g.

``````struct Struct
value::Int
end

value(x::Struct) = x.value
``````

An additional benefit is that this may simplify a later modification.

Here’s a better example than my previous one:

``````struct PropertyDict{V}
d::Dict{Symbol,V}
end

d(pd::PropertyDict) = getfield(pd, :d)
Base.getproperty(pd::PropertyDict, sym::Symbol) = d(pd)[sym]
Base.setproperty!(pd::PropertyDict, sym::Symbol, val) = ( d(pd)[sym] = val )
``````
``````julia> p = PropertyDict(Dict(:a => 1))
PropertyDict{Int64}(Dict(:a => 1))

julia> p.a
1

julia> p.b = 2
2

julia> p.b
2
``````

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.

That was just a question for the OP, basically why create syntactic sugar for `getfield` when `getproperty` already has it.

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.

1 Like

No, there is not (at least not at the time this is written).

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.

Yes. This is not problematic, but convenient, as fields provide a default for properties.

Of course, one is free to design an API where the two are distinct.

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`?

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…

1 Like

I don’t know any conventions, but you can do something like this for internal use… can’t avoid typing the `:` without a macro though:

``````julia> (..)(x, s::Symbol) = getfield(x, s);

julia> (1:3)'..:parent
1:3
``````
1 Like

Yes this is nicer, but operator precedence is not correct.

The following raises an error:

``````(..)(x, s::Symbol) = getfield(x, s);
(1:3)'..:parent .+ 1
``````

while

``````⋄ = getfield
(1:3)'⋄:parent .+ 1
``````

works as expected.

Oh yea, good point. You could shadow `^` since that has high precedence, and is easy to type:

``````^(x, s::Symbol) = getfield(x, s)
^(x,y) = Base.:^(x,y) # fall-through on other types
(1:3)'^:parent .+ 1
``````

There was an issue somewhere to make some more double-ascii operators with varying precedence, there is `++` but say `^^` would be neat here.

4 Likes

So far, `^` is the best solution!!
Thanks.