# OOP-like dot notation in Julia

**URL:** https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971
**Category:** Internals & Design
**Created:** [October 6, 2024, 11:18am UTC](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971 "2024-10-06T11:18:07Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![Barget](https://avatars.discourse-cdn.com/v4/letter/b/94ad74/32.png) [@Barget](https://discourse.julialang.org/u/Barget)
#### Post date: [October 6, 2024, 11:18am UTC](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971/1 "2024-10-06T11:18:07Z")

</div>

This is a naive question, but given the widespread use of the `object.method` notation in OOP languages, I struggle to find a sound reason as of why it can’t (or shouldn’t) be supported in Julia? I assumes this has something to do with code parsing, but what?

Consider the following:

- dot notation to access variable’s property is already well established (in a similar fashion as in C), using `foo.bar`
- this is just a sugar syntax that does `method(object, otherargs...)` … but really helpful to chain calls, discover code, and think about the code (the latter is admittedly subjective)
- Getting this notation to assign the left hand side of the dot to the first argument of the method seems quite arbitrary … but so is the `do ... end` block
- there is not risk of clash with the classical broadcasting dot notation for regular functions, for in this usual case, the dot is between the function’s name and a left parens
- There is no risk of clashing with the classical broadcasting dot notation for operators either, because colon is required when calling it from e.g. `Base.:+`, while broadcasting isn’t. In a similar fashion, using `variable.function` would just requires operators to be preceded by a colon, as in `foo.:+(bar)`
- I don’t see any potential breaking change than would require a hypothetical Julia2.0

I feel I’m missing a simple yet not obvious to me case that would prevent this notation to be properly parsed and interpreted.  
Or else, it is not supported because of other-than-parsing reasons? (and other than manpower)

… and if not … then wouldn’t it be great to have it available in Julia? 🙂

---

<div class="post-metadata">

### Author: ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)
#### Post date: [October 6, 2024, 11:29am UTC](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971/2 "2024-10-06T11:29:33Z")

</div>

I agree that it would be nice to have this feature. I would like it because it makes method discovery easier in the simple case that dispatch happens on the first argument.

---

<div class="post-metadata">

### Author: ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)
#### Post date: [October 6, 2024, 11:40am UTC](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971/3 "2024-10-06T11:40:05Z")

</div>

`a.b` in Julia means `getproperty(a, :b)`

```julia-repl
julia> Meta.@lower a.b
:($(Expr(:thunk, CodeInfo(
    @ none within `top-level scope`
1 ─ %1 = Base.getproperty(a, :b)
└── return %1
))))

```

Users can, [and often do](https://juliahub.com/ui/Search?type=symbols&q=getproperty&u=define), overload `getproperty` for their types.

---

<div class="post-metadata">

### Author: ![eldee](https://avatars.discourse-cdn.com/v4/letter/e/b5a626/32.png) [@eldee](https://discourse.julialang.org/u/eldee)
#### Post date: [October 6, 2024, 11:48am UTC](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971/4 "2024-10-06T11:48:54Z")

</div>

> [@Barget](#):
>
> this is just a sugar syntax that does `method(object, otherargs...)` … but really helpful to chain calls, discover code, and think about the code (the latter is admittedly subjective)

I don’t see why you would necessarily need dot notation for code discovery. Instead of typing `object.<TAB><TAB>` to get a list of methods, you could also (I imagine) add a keyboard shortcut (e.g. `object<CTRL + M>`) which then lists all applicable methods.

For chaining, the pipe operator `|>` exists (I’m not claiming this is flawless, but neither is dot notation in OOP).

---

<div class="post-metadata">

### Author: ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)
#### Post date: [October 6, 2024, 12:37pm UTC](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971/5 "2024-10-06T12:37:35Z")

</div>

> [@baggepinnen](#):
>
> Users can, [and often do](https://juliahub.com/ui/Search?type=symbols&q=getproperty&u=define), overload `getproperty` for their types.

But would that conflict with the suggested new functionality?

I don’t think so.

---

<div class="post-metadata">

### Author: ![co1emi11er](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/co1emi11er/32/206849_2.png) [@co1emi11er](https://discourse.julialang.org/u/co1emi11er)
#### Post date: [October 6, 2024, 12:42pm UTC](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971/6 "2024-10-06T12:42:41Z")

</div>

I think one issue with the `object.` approach is that say you had `foo.bar` to access a property and then you had a `bar(foo)` method. Those would then clash. (On second thought maybe this wouldn’t clash? You wouldn’t ever try to pass the function that way with `foo.bar`, so maybe julia would be able to distinguish between the two)

I think some sort of piping syntax is needed for better method discovery. The current syntax is fine, it just needs a little more power. The cool thing is, I think it could even be more powerful. Say you had an object `foo` that had `bar` and `baz` as some of its functions but `bar` had two different methods that `foo` was an explicit argument (like `bar(foo, arg2)` and `bar(arg1, foo)`). When you first do `foo |> ` you would get the list of functions like `bar` and `baz`, but once you complete `foo |> bar(` you then get the list of available bar methods explicit to `foo`. I think this could be awesome.

---

<div class="post-metadata">

### Author: ![xgdgsc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xgdgsc/32/608_2.png) [@xgdgsc](https://discourse.julialang.org/u/xgdgsc)
#### Post date: [October 6, 2024, 1:00pm UTC](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971/7 "2024-10-06T13:00:02Z")

</div>

This was already discussed at [Allowing the object.method(args…) syntax as an alias for method(object, args …) - Internals & Design - Julia Programming Language (julialang.org)](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051) . And a link to demo at [Allowing the object.method(args...) syntax as an alias for method(object, args ...) - #218 by xgdgsc](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/218)

---

<div class="post-metadata">

### Author: ![Barget](https://avatars.discourse-cdn.com/v4/letter/b/94ad74/32.png) [@Barget](https://discourse.julialang.org/u/Barget)
#### Post date: [October 6, 2024, 1:11pm UTC](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971/8 "2024-10-06T13:11:34Z")

</div>

Oh, thanks. I’ll try to search a bit longer next time.

---

<div class="post-metadata">

### Author: ![eldee](https://avatars.discourse-cdn.com/v4/letter/e/b5a626/32.png) [@eldee](https://discourse.julialang.org/u/eldee)
#### Post date: [October 6, 2024, 1:13pm UTC](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971/9 "2024-10-06T13:13:46Z")

</div>

> [@Barget](#):
>
> this is just a sugar syntax

You can always add syntactic sugar yourself via a macro (though it is of course slightly less clean than if it were natively supported, as you need to use `@`).

```julia
using MacroTools: @capture, postwalk

macro dm(ex) # dot method
    return postwalk(ex) do x
        if @capture(x, obj_.f_(args__)) && !in(f, fieldnames(typeof(eval(obj))))
            # (I'm not too fond of the eval here, but I don't see how else to get the list of fields of a symbol representing an instance.)
            return :($f($obj, $(args...)))
        else
            return x
        end
    end
end

```

```julia-repl
julia> struct S{F <: Function}
           a::Int
           f::F # To have s.t(x) both for when t is a field function, and when it is an external function
       end;

julia> plus1(s::S{F}) where F = S{F}(s.a + 1, s.f);

julia> plus(s::S{F}, t::S{F}) where F = S{F}(s.a + t.a, s.f);

julia> F = typeof(sin); s = S{F}(1, sin); t = S{F}(2, sin);

julia> @dm s.plus(t) # becomes plus(s, t) --> .a == 3
S{typeof(sin)}(3, sin)

julia> @dm s.plus1() # becomes plus1(s) --> .a == 2
S{typeof(sin)}(2, sin)

julia> @dm s.f(pi) # remains s.f(pi) (== sin(pi) == 0), requires the fieldnames part in the macro to not change this into f(s, pi)
0.0

julia> @dm s.f.([0, pi]) # (dot broadcasting still works)
2-element Vector{Float64}:
 0.0
 1.2246467991473532e-16

julia> f(x) = 4; @dm s.f(pi) # again sin(pi), not f(pi) == 4
0.0

```

If this helps you to think about code, you could use such a macro (if necessary tweaked to be more robust). This might also help you with discovering any possible shortcomings, if they exist.

---

<div class="post-metadata">

### Author: ![Barget](https://avatars.discourse-cdn.com/v4/letter/b/94ad74/32.png) [@Barget](https://discourse.julialang.org/u/Barget)
#### Post date: [October 6, 2024, 1:17pm UTC](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971/10 "2024-10-06T13:17:14Z")

</div>

I agree, using macro is always possible as a last resort solution. But this is slightly beside the point, which is to have a native support, and wouldn’t be compatible with tab completion. Thanks for the proposal, though.

> [@co1emi11er](#):
>
> I think one issue with the `object.` approach is that say you had `foo.bar` to access a property and then you had a `bar(foo)` method. Those would then clash.

Hmm, I’d be surprise if it were possible in Python to declare a property and a method of a class with the same name. Clash would be prevented.

> [@eldee](#):
>
> For chaining, the pipe operator `|>` exists (I’m not claiming this is flawless, but neither is dot notation in OOP).

Unfortunately, each time I give a chance to this approach, I end up creating anonymous functions at each piping step, which is very teddious. This is usually to do currying using the return value of the previous step. To me, this is a very common pattern for which I have hard times trying to find reasonable alternatives.

> [@baggepinnen](#):
>
> `a.b` in Julia means `getproperty(a, :b)`

I agree (and mentioned it in the OP), but don’t see how this would prevent this other meaning of dot. It’s possible to propose a list of match, and to specify whether this is a property or a method (for tab completion).  
The only issue I see is when doing `c = a.b`, where the intend is to store a function `b` into `c`. Quite convoluted, and could be forbidden by design, to be favored to the property extraction accompanied with a warning. As for soft scopes when dealing with ambiguity.

> [@xgdgsc](#):
>
> This was already discussed at [Allowing the object.method(args…) syntax as an alias for method(object, args …) - Internals & Design - Julia Programming Language (julialang.org)](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051) .

Following this thread of links, I ended up at: [oop - How to create a "single dispatch, object-oriented Class" in julia that behaves like a standard Java Class with public / private fields and methods - Stack Overflow](https://stackoverflow.com/questions/39133424/how-to-create-a-single-dispatch-object-oriented-class-in-julia-that-behaves-l/39150509#39150509)  
This is almost what I was thinking about, except that it’s a very OOP-specific solution.

---

<div class="post-metadata">

### Author: ![co1emi11er](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/co1emi11er/32/206849_2.png) [@co1emi11er](https://discourse.julialang.org/u/co1emi11er)
#### Post date: [October 6, 2024, 1:33pm UTC](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971/11 "2024-10-06T13:33:57Z")

</div>

This is pretty great. Have you been using this for some time now? How would I go about using this?

I guess there is somewhere that the Julia vscose plugin lives on my computer and I would just replace it with your version?

---

<div class="post-metadata">

### Author: ![eldee](https://avatars.discourse-cdn.com/v4/letter/e/b5a626/32.png) [@eldee](https://discourse.julialang.org/u/eldee)
#### Post date: [October 6, 2024, 1:50pm UTC](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971/12 "2024-10-06T13:50:24Z")

</div>

> [@Barget](#):
>
> Unfortunately, each time I give a chance to this approach, I end up creating anonymous functions at each piping step, which is very teddious. This is usually to do currying using the return value of the previous step. To me, this is a very common pattern for which I have hard times trying to find reasonable alternatives.

There are plenty of packages providing macros to solve this exact inconvenience, e.g. Chain.jl, Pipe.jl, Underscores.jl.

```julia-repl
julia> using Underscores

julia> @_ rand(10) |> filter(0.4 < _ < 0.6, __) # equivalent to rand(10) |> x -> filter(t -> 0.4 < t < 0.6, x)
2-element Vector{Float64}:
 0.4728989701850077
 0.4825616604480252

```

---

<div class="post-metadata">

### Author: ![co1emi11er](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/co1emi11er/32/206849_2.png) [@co1emi11er](https://discourse.julialang.org/u/co1emi11er)
#### Post date: [October 6, 2024, 1:58pm UTC](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971/13 "2024-10-06T13:58:49Z")

</div>

> [@Barget](#):
>
> Hmm, I’d be surprise if it were possible in Python to declare a property and a method of a class with the same name. Clash would be prevented.

Yeah you wouldn’t be able to. That’s because the method lives inside the class. I think it would be perfectly fine in python to do if the function lived outside the class but you wouldn’t get the `.` capabilities. All functions/methods live outside the class in Julia so it would be harder to check maybe was my thought, but yeah I think it could be okay anyway since you wouldn’t ever need to pass that function that way as an object.

Anyway, I am perfectly fine with `.` over `|>` if that works. I’m glad you made this thread!

---

<div class="post-metadata">

### Author: ![Barget](https://avatars.discourse-cdn.com/v4/letter/b/94ad74/32.png) [@Barget](https://discourse.julialang.org/u/Barget)
#### Post date: [October 6, 2024, 2:02pm UTC](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971/14 "2024-10-06T14:02:52Z")

</div>

> [@co1emi11er](#):
>
> All functions/methods live outside the class in Julia so it would be harder to check maybe was my thought

Oh, right. I eventually addressed it in my edited response above (tab discovery vs compile check).

---

<div class="post-metadata">

### Author: ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)
#### Post date: [October 6, 2024, 2:03pm UTC](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971/15 "2024-10-06T14:03:17Z")

</div>

> [@ufechner7](#):
>
> But would that conflict with the suggested new functionality?
> 
> I don’t think so.

Of course it would, how would you know whether `a.b()` means `getproperty(a, :b)()` or `b(a)`?

---

<div class="post-metadata">

### Author: ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)
#### Post date: [October 6, 2024, 2:28pm UTC](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971/16 "2024-10-06T14:28:55Z")

</div>

Well, if there is no such property it could look for a function call with this signature and vice versa. If there is both it could throw an error.

---

<div class="post-metadata">

### Author: ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)
#### Post date: [October 6, 2024, 2:45pm UTC](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971/17 "2024-10-06T14:45:53Z")

</div>

No that does not work, you cannot generally know whether the property exist before you have actually executed the `getproperty` function. It would also be a _hugely_ breaking change to start introducing an error for a propert access that was previously working.

---

<div class="post-metadata">

### Author: ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)
#### Post date: [October 6, 2024, 2:51pm UTC](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971/18 "2024-10-06T14:51:14Z")

</div>

> [@Barget](#):
>
> this is just a sugar syntax that does `method(object, otherargs...)` … but really helpful to chain calls, discover code

For function discovery, a better autocomplete would indeed be useful!  
Does it have to be `object.<tab>`? Maybe, but also consider alternatives that mesh better with the existing Julia syntax – eg, `?(object<tab>` or similar.  
Anyway, autocomplete is not currently limited by the lack of syntax, and could definitely be improved.

> [@Barget](#):
>
> Unfortunately, each time I give a chance to this approach, I end up creating anonymous functions at each piping step, which is very teddious. This is usually to do currying using the return value of the previous step. To me, this is a very common pattern for which I have hard times trying to find reasonable alternatives.

Many Julia functions that one commonly wants to pipe take either a function or some model object as the first argument, while the natural “object” goes as the second/last argument.  
[DataPipes.jl](https://github.com/JuliaAPlavin/DataPipes.jl) ([discussion](https://discourse.julialang.org/t/ann-datapipes-jl-0-3-0/60734)) is specifically designed for zero-boilerplate piping in this very common scenario, while still supporting functions that take the “object” as the first argument.  
Not sure if using `.` for piping is much more convenient to warrant such major changes…

---

<div class="post-metadata">

### Author: ![Barget](https://avatars.discourse-cdn.com/v4/letter/b/94ad74/32.png) [@Barget](https://discourse.julialang.org/u/Barget)
#### Post date: [October 6, 2024, 3:56pm UTC](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971/19 "2024-10-06T15:56:20Z")

</div>

> [@aplavin](#):
>
> Does it have to be `object.<tab>`? Maybe, but also consider alternatives that mesh better with the existing Julia syntax – eg, `?(object<tab>` or similar.

Indeed, this may be seen as two distinct issues. My feeling is that is common and convient enough in other languages that there’s no need to reinvent the wheel, and would help “welcoming” newcomers. But we should not refrain ourself to think outside the proverbial box.

> [@aplavin](#):
>
> DataPipes.jl

Thanks for the link, didn’t know this package.

> [@baggepinnen](#):
>
> No that does not work, you cannot generally know whether the property exist before you have actually executed the `getproperty` function.

Well, I don’t see how this would be an issue, given that this can be checked at compile time. `getproperty` is how the REPL implements it. But the compiler can do otherwise.  
Also, in vanilla Julia, you can already try to do `a.b`, and get an error if it `b` doesn’t exist (with the compiler).

> [@baggepinnen](#):
>
> It would also be a _hugely_ breaking change to start introducing an error for a propert access that was previously working.

Same answer here, I’m not sure whether this would be _hugely_ breaking … if at all: consider to give a higher precedence to `getproperty` over a possible “syntax replacement” to call `b(a)`. And raise a warning if there’s an ambiguity, stating that `getproperty` is done by default (this is not new: see soft scope).

The only issue I see so far is when `b` is a type with a defined functor, such as:

```julia-auto
struct SomeInnerType
   val::Int
end 
bar = SomeInnerType(1)

struct SomeOuterType
   b:: SomeInnerType
end
a = SomeOuterType(bar)

b(x) = x + 2 # defines a function with potential name conflict

@assert a.b(3) == 5 # OK, no ambiguity

c = a.b
@assert typeof(c) == SomeInnerType # + ambiguity warning, could be function b, but still works

(b::SomeInnerType)(x) = x + b.val

@assert a.b(3) == 4 # + ambiguity warning

```

This still works, is not breaking. Admittedly, this would be hard to debug in case of a heavy reliance on dynamic creation of functions and/or macro. But there is a trade-off to be made here, regarding potential gains/pains. As discussions on the `transpose` operation have shown, full consistency and perfection is not always possible. Sometime, it is worth being a bit pragmatic.

Maybe another simple solution would be to simply call `a..b()` for methods instead of the classical `a.b()` for properties? (open to other symbols, of course)

---

<div class="post-metadata">

### Author: ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)
#### Post date: [October 6, 2024, 4:08pm UTC](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971/20 "2024-10-06T16:08:07Z")

</div>

> [@Barget](#):
>
> Well, I don’t see how this would be an issue, given that this can be checked at compile time. `getproperty` is how the REPL implements it. But the compiler can do otherwise.  
> Also, in vanilla Julia, you can already try to do `a.b`, and get an error if it `b` doesn’t exist (with the compiler).

It’s generally not possible to determine available properties without executing `propertynames(obj)` or `getproperty(obj, propname)`. Remember that these functions may contain arbitrary Julia code.

For example, consider types like [GitHub - JuliaCollections/PropertyDicts.jl](https://github.com/JuliaCollections/PropertyDicts.jl) – the list of properties depends on the value, and cannot be determined from the type alone.

[Next page](https://discourse.julialang.org/t/oop-like-dot-notation-in-julia/120971.md?page=2)
