# Accessing type internal fields in package interfaces

**URL:** https://discourse.julialang.org/t/accessing-type-internal-fields-in-package-interfaces/70263
**Category:** General Usage
**Tags:** question
**Created:** [October 23, 2021, 1:50pm UTC](https://discourse.julialang.org/t/accessing-type-internal-fields-in-package-interfaces/70263 "2021-10-23T13:50:20Z")
**Posts on this page:** 1
**Showing post:** 15

<div class="post-metadata">

### Author: ![akb](https://avatars.discourse-cdn.com/v4/letter/a/5daacb/32.png) [@akb](https://discourse.julialang.org/u/akb)
#### Post date: [October 27, 2021, 9:55pm UTC](https://discourse.julialang.org/t/accessing-type-internal-fields-in-package-interfaces/70263/15 "2021-10-27T21:55:17Z")

</div>

### Cost of public properties

1. In my view, the main advantage of Julia’s multiple dispatch is that it allows everybody equal ability to define public functions of `x::X`, rather than privileging the owner of `X`. As a function author, I can write new functions that look and feel like they belong on `x` just as much as `X`’s author can.

2. It is useful when writing a package to think about the public interface separately from the implementation. Public properties reduce the delineation between interface and implementation, and may cause implementation details to leak into interfaces unnecessarily.

So public properties come at a significant cost.

### Benefits of public properties

1. At the definition site, using properties means authors don’t have to write out the definition of the getters:

```julia-auto
struct Person
name
age
end

```

is shorter than

```julia-auto
struct Person
name
age
end
name(p::Person) = p.name
age(p::age) = p.age

```

1. At the call site, `person.name` needs one fewer character than `name(person)`.

2. At the call site, `person.name |> length` puts the property on the right rather than the left of `name(person) |> length`, so chains are read linearly in left-to-right order.

3. At the call site, if multiple packages in scope provide functions `name` for their objects, they need to be used in package-namespaced form `Persons.name(person)` or imported under a different name like `using Persons: name as pname`, while `person.name` does not.

4. At the call site, dot syntax can [hint](https://internals.rust-lang.org/t/idea-properties/11152/12) at certain information about a property access. Namely, `person.name` indicates it does not require expensive computation, does not raise an error, and does not change its value unless otherwise mutated.

### Analysis

Benefits 1,2,3 are issues of surface syntax that can be solved with a macro or operator, without paying Cost 1 of public properties.

For Benefit 1,

```julia-auto
@getters struct Person
name
@nogetter age
end

```

could define `name(p::Person) = p.name` without the user having to write it out.

For Benefit 2 and Benefit 3, various packages such as [Chain.jl](https://github.com/jkrumbiegel/Chain.jl) have been exploring chaining interfaces.

For example,

```julia-auto
using Chain

struct Person
name
age
end
name(p::Person) = p.name

> person = Person("Alice", 99);
> @chain person name length
# 5

```

This chain is read linearly in left-to-right order (Benefit 3).  
The chain doesn’t require parentheses (Benefit 2) though it does require `@chain`. The function-on-the-right invocation can also be written `person|>name` in the same number of characters as `name(person)` and one more than `person.name`.

A bigger change would be making a property `p` only accessible via function call `p(x)`, and `x.p` just a shortcut equivalent to `@chain x p`. If desired, `x.p` might automatically disambiguate to `parentmodule(x).p(x)` if there is another `p` in the calling scope. This would require experimentation to see where it causes breakage.

Benefit 4 (name collisions) remains but I believe it is small because the function import can be handled once at the top of the caller’s file.

Benefit 5 (property hinting) seems hardest to attain without dot-access properties, because hinting at those properties is essentially a form of documentation rather than a fact about the code. This could be done with prose documentation, or a form of code specification adjacent to each function definition.

### Conclusions

Most of the advantages of public properties can be obtained in a functional API without the downsides. Some changes will make that easier:

- Make it easier to define getters and setters. Promote the use of `@getters` where appropriate and consider including it in Base.

- Make it easier to chain calls. Promote `|>` and Chain.jl.

- For radicals [duly cautioned](https://discourse.julialang.org/t/psa-julia-is-not-at-that-stage-of-development-anymore/44872), consider making a property `p` only accessible via function call, and `x.p` equivalent to `@chain x p`.

- Examine structured ways of specifying function properties like “constant value”, “low-cost access”, and “non-erroring”, and more.

---

_[View the full topic](https://discourse.julialang.org/t/accessing-type-internal-fields-in-package-interfaces/70263)._
