# Allowing the object.method(args...) syntax as an alias for method(object, args ...)

**URL:** <https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051>\
**Category:** Internals & Design\
**Tags:** question, design\
**Created:** [May 29, 2021, 5:09pm UTC](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051 "2021-05-29T17:09:54Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [May 31, 2021, 2:15pm UTC](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/43 "2021-05-31T14:15:51Z")

</div>

Going back to your original example, my impression is that the way of thinking it is not the natural way to think it in Julia. You defined a `type` for a filter, where it would be more natural to define a function directly, such as:

```julia
function IIRfilter(xv;state=nothing,alpha=0.5)
   @assert 0 <= alpha <= 1 "alpha must be between 0 and 1"
   xf = similar(xv)
   if state == nothing
     state = xv[begin]
   end
   for i in eachindex(xv)
      xf[i] = alpha*state + (1 - alpha)*xv[i]
      state = xf[i]
   end
   return xf
end

```

and use it with:

```julia
xv = rand(3000)
xf = IIRfilter(xv,alpha=0.9)

```

maybe in Julia we separe more the data (`xv`) from the action over the data (the filter). This is not directly related to the original post, but maybe is a way to start moving to a more function-centered programming, which will be more natural in Julia.

Another small things:

> [@gianmariomanca](#):
>
> ```julia
> for i = collect(1:N)
> xf[i] = filter(f,xv[i])
> end
> 
> ```

This can be written as (and `collect` there will create an unnecessary vector):

```julia
for i in 1:N
  xf[i] = filter(f,xv[i])
end

```

or as

```julia
xf = filter.(f,xv)

```

where the `.` indicates broadcasting. (maybe this does not work in your case because the operations depend on the previous state).

> [@gianmariomanca](#):
>
> `	xv = randn(N,1);`

This is `rand(N)` (there is a difference in Julia between a matrix with one column and a vector, probably you want a vector there).

---

<div class="post-metadata">

**Author:** ![gianmariomanca](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gianmariomanca/32/25597_2.png) [@gianmariomanca](https://discourse.julialang.org/u/gianmariomanca)\
**Post date:** [May 31, 2021, 2:23pm UTC](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/44 "2021-05-31T14:23:55Z")

</div>

@Tamas_Papp , it’s more like going to Italy and saying, can you please add the expected time of arrival of the next bus at the bus stop so I don’t sit for half an hour wondering if I will ever reach my hotel or my plane on time? (You don’t have to be like Japan where they start an investigation for a 1-minute delay, but you know somewhere between Germany and Spain)

---

<div class="post-metadata">

**Author:** ![gianmariomanca](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gianmariomanca/32/25597_2.png) [@gianmariomanca](https://discourse.julialang.org/u/gianmariomanca)\
**Post date:** [May 31, 2021, 2:29pm UTC](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/45 "2021-05-31T14:29:52Z")

</div>

@lmiq if the input is not available all at once (i.e. you get one sample at a time, you update the filter, do something else, etc) you need to maintain the state between multiple calls, that’s why I used the “object” approach.

---

<div class="post-metadata">

**Author:** ![arch.d.robison](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/arch.d.robison/32/17699_2.png) [@arch.d.robison](https://discourse.julialang.org/u/arch.d.robison)\
**Post date:** [May 31, 2021, 2:30pm UTC](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/46 "2021-05-31T14:30:05Z")

</div>

In C++, the desire to use the dot syntax sometimes leads to poor design, because users become more focused on the syntax than the design. Examples:

- There is no way to forward-declare C++ methods. That can lead to #include bloat that slows down compilation.
- Making all functions that can act on an object into methods leads to kitchen-sink design. I tend towards providing only enough methods to complete the abstraction.
- The syntax works only for classes/structs. Hence it’s often inappropriate for the signature-based style used for template programming. E.g., C++ STL decouples algorithms from containers by making the algorithms stand-alone functions.

So I find myself using method _less_ these days in C++ than when I started using C++ in 1988, and instead use more stand-alone functions.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [May 31, 2021, 2:49pm UTC](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/47 "2021-05-31T14:49:35Z")

</div>

> [@gianmariomanca](#):
>
> (You don’t have to be like Japan where they start an investigation for a 1-minute delay, but you know somewhere between Germany and Spain)

I know it’s just an example, but Germany is a particularly bad analogy since in some cases trains that are delayed too much may not arrive at all and instead just turn around midway. If it never arrives, it can’t be late, making for a better statistic 🤷‍♂️ ([Source in german](https://www.youtube.com/watch?v=0rb9CfOvojk))

> [@gianmariomanca](#):
>
> if the input is not available all at once (i.e. you get one sample at a time, you update the filter, do something else, etc) you need to maintain the state between multiple calls, that’s why I used the “object” approach.

In that case, an [iterator approach](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-iteration) (which carries its state as part of the protocol, not as part of a struct) may be preferrable.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [May 31, 2021, 2:50pm UTC](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/48 "2021-05-31T14:50:52Z")

</div>

> [@gianmariomanca](#):
>
> it’s more like going to Italy and saying, can you please add the expected time of arrival of the next bus at the bus stop

This metaphorical race will never stop, I realize, but I disagree that it is _more_ like the bus analogy than the pizza analogy.

I _do_ think this is a pretty fundamental change, along the lines of “please replace your time- and work intensive slow-cooking cuisine with convenient, affordable and cheap highly processed industrial food.”

Easy and quick to prepare, yeah. Good for you…?

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [May 31, 2021, 3:02pm UTC](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/49 "2021-05-31T15:02:21Z")

</div>

That is fine. The approach that @mcabbott roposed there (the functor) may the best one, then. Anyway, this is what it could look like:

```julia
using Parameters

@with_kw mutable struct IIRfilter
  @assert 0 <= alpha <= 1 "alpha must be between 0 and 1"
  state::Union{Float64,Nothing} = nothing
  alpha::Float64
end

# Apply to a single number
function (f::IIRfilter)(x::Number)
  if f.state == nothing
    f.state = x
  else
    f.state = f.alpha*f.state + (1-f.alpha)*x
  end
  return f.state
end

# Apply filter to a vector
function (f::IIRfilter)(x::AbstractVector)
  xf = similar(x)
  for i in eachindex(x)
    xf[i] = f(x[i]) # this calls the definition above
  end
  return xf
end

# set data
n = 3000
xv = rand(n)

# set filter
filter = IIRfilter(alpha=0.9)

# Use on a vector
xf = filter(xv)

# Use on a single data point
x = filter(1.0)

```

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [May 31, 2021, 3:15pm UTC](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/50 "2021-05-31T15:15:05Z")

</div>

> [@gianmariomanca](#):
>
> “discovery and auto-completion in Julia”

Generally, multiple dispatch allows packages to expose a small and concise API. People just read the docs, use the functionality in [InteractiveUtils](https://docs.julialang.org/en/v1/stdlib/InteractiveUtils/), or grep the source code.

In most cases you don’t have to navigate tons of methods, just a small vocabulary. For example, consider [arrays](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-array), one of the core building blocks of the language: a user would learn about `size` and `[]` (`getindex`, `setindex!`), and cover 90% of use cases. The remaining few verbs (`similar`, `axes`) complete the picture.

Or consider [Optim.jl](https://github.com/JuliaNLSolvers/Optim.jl), a powerful optimization package written in native Julia. It exports _two_ functions: `optimize` and `maximize`.

Julia is noun-, not verb-heavy.

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [May 31, 2021, 3:21pm UTC](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/51 "2021-05-31T15:21:45Z")

</div>

> [@Sukera](#):
>
> I know it’s just an example, but Germany is a particular bad analogy

In Italy we have the idea that everything in Germany is perfect and trains are on time. Having actually lived in Germany for some months I learned that Germany isn’t as perfect as we like to think and trains aren’t necessarily more timely than in Italy (it’s pretty much the opposite)

---

<div class="post-metadata">

**Author:** ![gianmariomanca](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gianmariomanca/32/25597_2.png) [@gianmariomanca](https://discourse.julialang.org/u/gianmariomanca)\
**Post date:** [May 31, 2021, 3:45pm UTC](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/52 "2021-05-31T15:45:08Z")

</div>

@giordano , sorry for using a stereotype, it’s never great, but to give some background I’m Italian (born in Sardinia), studied in Pisa and Parma, I lived and worked in Germany in Munich and Berlin (great public transportation) mostly doing research in theoretical/computational Physics and Astrophysics at the Max Planck Institute, traveled quite a bit, I lived in LA, and now live in Silicon Valley, as a US citizen married to an Armenian. Last vacation was spent in agriturismos in Assisi, Gubbio, Bologna plus sometime on the beaches of Sardinia: I highly recommend visiting Italy, don’t get me wrong 🙂 (and I recommend agriturismos, doing some research with a bit of luck you’ll find a great host and have a wonderful experience)

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [May 31, 2021, 5:01pm UTC](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/53 "2021-05-31T17:01:08Z")

</div>

> [@giordano](#):
>
> trains are on time

![](https://global.discourse-cdn.com/julialang/original/3X/4/5/455cb2022c054a73d109d332d9e0b990c2b81dd8.png)

---

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [May 31, 2021, 7:50pm UTC](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/55 "2021-05-31T19:50:04Z")

</div>

> [@Tamas\_Papp](#):
>
> In most cases you don’t have to navigate tons of methods, just a small vocabulary. For example, consider [arrays](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-array), one of the core building blocks of the language: a user would learn about `size` and `[]` ( `getindex` , `setindex!` ), and cover 90% of use cases. The remaining few verbs ( `similar` , `axes` ) complete the picture.
> 
> Or consider [Optim.jl](https://github.com/JuliaNLSolvers/Optim.jl), a powerful optimization package written in native Julia. It exports _two_ functions: `optimize` and `maximize` .
> 
> Julia is noun-, not verb-heavy.

It’s true that at the bottom there are often only a few functions that a library needs, but new programmers can be misled by this. Because of multiple dispatch, there are often many higher-level functions that can automatically use the few core functions. And, I believe that proliferation of verbs (e.g. [IterTools.jl](https://juliacollections.github.io/IterTools.jl/latest/)) that work on a simple interface is a very good thing. The alternative to _many_ functions is _few_ functions with [messy semantics](https://discourse.julialang.org/t/what-is-the-difference-between-rand-and-sample/52297/8), and that should be avoided.

The way to have clear and composable APIs is to have a lot of distinguishable functions with clear contracts. In Julia, those functions can all act on many data types automatically, but that should not obscure the guiding principle that a function should do one thing clearly.

I want more verbs!

---

<div class="post-metadata">

**Author:** ![gianmariomanca](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gianmariomanca/32/25597_2.png) [@gianmariomanca](https://discourse.julialang.org/u/gianmariomanca)\
**Post date:** [June 2, 2021, 1:15am UTC](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/56 "2021-06-02T01:15:35Z")

</div>

@leandromartinez98 see [Allowing the object.method(args...) syntax as an alias for method(object, args ...) - #23 by gianmariomanca](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/23)

PS thank you for the example, still interesting.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [June 10, 2021, 8:44pm UTC](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/57 "2021-06-10T20:44:39Z")

</div>

One random thought I had today

```julia
struct PseudoClass{T}
    data::T
end

(o::PseudoClass)(f, args...; kwargs...) = f(o.data, args...; kwargs...)

```

This lets you write `o(f, args...)` the way you’d write `o.f(args...)` in class based languages:

```julia
julia> let x = PseudoClass(1)
           x(+, 1)
       end
2

julia> let s = PseudoClass(["apples", "bananas", "pineapples"])
           s(join, ", ")
       end
"apples, bananas, pineapples"

```

Interestingly enough, it also synergizes with julia’s `do` notation:

```julia
julia> let v = PseudoClass(1:5)
           v(1) do v, x
               z = 0
               for y in v
                   z += (y - x) / (y + x)
               end
               z
           end
       end
2.0999999999999996

```

And because it’s functions you’re sticking in the first argument to the pseudoclass, tab completion will work (though it won’t be method-aware):

```julia
julia> v(fi<TAB>)

fieldcount fieldoffset filemode fill! finalize findall findmax findmin! first
fieldname fieldtype filesize filter finalizer findfirst findmax! findnext firstindex
fieldnames fieldtypes fill filter! finally findlast findmin findprev
julia> v(fil<TAB>)

filemode filesize fill fill! filter filter!
julia> v(fil)

```

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [June 10, 2021, 8:51pm UTC](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/58 "2021-06-10T20:51:20Z")

</div>

Even more fun is that on version 1.6 and up, you can define a postfix operator that does this:

```julia
julia> var"'ᶜ" = PseudoClass
PseudoClass

julia> 1'ᶜ(*, 3, [4, 5, 6])
3-element Vector{Int64}:
 12
 15
 18

julia> [3, 4, 5]'ᶜ(dot, [6, 7, 8])
86

```

---

<div class="post-metadata">

**Author:** ![jessymilare](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jessymilare/32/13750_2.png) [@jessymilare](https://discourse.julialang.org/u/jessymilare)\
**Post date:** [June 13, 2021, 6:23pm UTC](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/59 "2021-06-13T18:23:46Z")

</div>

Another example using `getproperty`.

```julia
struct Class{T}
    __data__ ::T
    __module__ ::Module
end

macro class(data)
    :($Class($(esc(data)), @ __MODULE__ ))
end

function Base.getproperty(class::Class, key::Symbol)
    if key == : __data__
        getfield(class, : __data__ )
    elseif key == : __module__
        getfield(class, : __module__ )
    elseif key == :get_class_data
        () -> class. __data__
    elseif hasproperty(class. __data__ , key)
        class. __data__.key
    else
        try
            func = getproperty(class. __module__ , key)
            if func isa Function
                return (args...; kwargs...) -> Class(func(class. __data__ , args..., kwargs...), class. __module__ )
            end
        catch
        end
        Class(getfield(class. __data__ , key))
    end
end

```

```julia
julia> @class(1).:+(2,3)
Class{Int64}(6, Main)

julia> @class(1).:+(2,3).get_class_data()
6

julia> plus = +
+ (generic function with 190 methods)

julia> @class(1).plus(2,3).get_class_data()
6

julia> @class(1).bar()
ERROR: type Int64 has no field bar
Stacktrace:
 [1] getproperty(class::Class{Int64}, key::Symbol)
   @ Main ./REPL[40]:18
 [2] top-level scope
   @ REPL[50]:1

```

Tab completion can also work implementing a `propertynames` method.

---

<div class="post-metadata">

**Author:** ![jessymilare](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jessymilare/32/13750_2.png) [@jessymilare](https://discourse.julialang.org/u/jessymilare)\
**Post date:** [June 13, 2021, 8:46pm UTC](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/60 "2021-06-13T20:46:01Z")

</div>

My 2c. I honestly don’t understand why people think that `object.method(args...)` is simpler syntax than `method(object, args...)`. Of course, that must be because I first learned C, then Matlab, Common Lisp, Scheme, Python, then Julia (not including languages which I learned but didn’t use much). The Python syntax does make some sense in Python, specially for simple functions in which the first argument is special. But it becomes a headache when what you want is two or three-args methods (e.g., the ` __add__ ` method and friends).

I don’t understand why it is natural for some people that methods to belong to objects. That makes absolutely no sense to me. Methods are functions, functions don’t belong to their domains. Of course, it is possible, in Python, to create methods after the class definition, but that is not idiomatic. However, quite often it makes sense to define new methods that work with classes defined by someone else (e.g. math functions with number classes).

IMHO, what Julia lacks is some built-in simple support for chaining, but I would prefer a syntax that makes clear that the method doesn’t belong to the object (like the `@chain` macro above, or like `x |> f(_, y, z) |> g(_, w)` which is being proposed).

---

<div class="post-metadata">

**Author:** ![jessymilare](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jessymilare/32/13750_2.png) [@jessymilare](https://discourse.julialang.org/u/jessymilare)\
**Post date:** [June 13, 2021, 9:13pm UTC](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/61 "2021-06-13T21:13:47Z")

</div>

By the way, you can easily do in Julia what you do with Python’s methods, even if it takes more characters. It is not so easy the other way around. There are modules which implement multiple dispatch in Python, but they are not as complete as Julia’s dispatch.

---

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [June 13, 2021, 9:55pm UTC](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/62 "2021-06-13T21:55:59Z")

</div>

It would be nice to have a way that’s

- just syntax sugar for normal function call
- very short (e.g. 1 character, normally used without spaces)
- built into the language
- considered idiomatic

```julia
julia> "x |> f(_, y)" |> length # pipe proposal
12

julia> "x.f(y)" |> length # Nim style 
6

julia> "x⤷f(y)" |> length # unicode character
6

```

---

<div class="post-metadata">

**Author:** ![jessymilare](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jessymilare/32/13750_2.png) [@jessymilare](https://discourse.julialang.org/u/jessymilare)\
**Post date:** [June 14, 2021, 2:37am UTC](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051/63 "2021-06-14T02:37:39Z")

</div>

I agree it would be nice to have a syntax sugar, but I don’t agree shorter is always best (e.g. Perl scripts). IMO, clear, flexible and consistent is better than short (I think 1 char is not enough for clarity, flexibility and consistency).

[Previous page](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051.md?page=2)

[Next page](https://discourse.julialang.org/t/allowing-the-object-method-args-syntax-as-an-alias-for-method-object-args/62051.md?page=4)
