# Is it possible to define a \`\`+!\`\` function?

**URL:** https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475
**Category:** General Usage
**Created:** [September 11, 2020, 7:41pm UTC](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475 "2020-09-11T19:41:52Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)
#### Post date: [September 11, 2020, 7:41pm UTC](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475/1 "2020-09-11T19:41:52Z")

</div>

Tried this but no luck.

```julia
julia> (+!)(x, y) = 0
ERROR: syntax: invalid function name "+(!)" around REPL[35]:1

or

julia> function +!(x, y) = 0 end
ERROR: syntax: expected "end" in definition of function "+"

```

The idea is to apply it to two custom types and add them in _situ_.

Thanks

---

<div class="post-metadata">

### Author: ![lostella](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lostella/32/356_2.png) [@lostella](https://discourse.julialang.org/u/lostella)
#### Post date: [September 11, 2020, 7:48pm UTC](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475/2 "2020-09-11T19:48:18Z")

</div>

I guess for numbers or arrays the following would work:

```julia
a .+= b

```

So maybe you want to define some custom broadcasting rules for your types? See here: [Interfaces · The Julia Language](https://docs.julialang.org/en/v1/manual/interfaces/#man-interfaces-broadcasting)

---

<div class="post-metadata">

### Author: ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)
#### Post date: [September 11, 2020, 7:55pm UTC](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475/3 "2020-09-11T19:55:29Z")

</div>

You can use `Meta.@dump` to get an insight into how the parser interprets `+!`:

```julia
julia> Meta.@dump(1 +! 2)
Expr
  head: Symbol call
  args: Array{Any}((3,))
    1: Symbol +
    2: Int64 1
    3: Expr
      head: Symbol call
      args: Array{Any}((2,))
        1: Symbol !
        2: Int64 2

```

We see that `1 +! 2` is just equivalent to `+(1, !(2))`, so we can’t use it as an infix operator, or in fact as any valid identifier. Another way to check this are `Base.isoperator` and `Base.isidentifier`:

```julia
julia> Base.isoperator("+!")
false

julia> Base.isidentifier("+!")
false

```

You can use arbitrary names as identifiers with the `var` string literal, like `var"+!"`, but I don’t know if that’s what you are after.

---

<div class="post-metadata">

### Author: ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)
#### Post date: [September 11, 2020, 8:00pm UTC](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475/4 "2020-09-11T20:00:15Z")

</div>

You can of course be sneaky, but it’s a bit of an ugly solution, because you are actually overloading `!`:

```julia
julia> struct A end

julia> struct B end

julia> struct Not
           x::B
       end

julia> Base.:!(x::B) = Not(x)

julia> Base.:+(::A, ::Not) = print("Boo!")

julia> A() +! B()
Boo!

```

---

<div class="post-metadata">

### Author: ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)
#### Post date: [September 11, 2020, 8:11pm UTC](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475/5 "2020-09-11T20:11:27Z")

</div>

I could live with the _ugly_ but the problem is that I would also want `-!, *!, /!, ^! ...`

---

<div class="post-metadata">

### Author: ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)
#### Post date: [September 11, 2020, 8:14pm UTC](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475/6 "2020-09-11T20:14:47Z")

</div>

That’s easy, you can just overload `Base.:-(::A, ::Not)`, `Base.:*(::A, ::Not)`, etc. Just keep in mind that this only really works if you actually own the type on the right.

---

<div class="post-metadata">

### Author: ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)
#### Post date: [September 11, 2020, 8:17pm UTC](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475/7 "2020-09-11T20:17:18Z")

</div>

Yes, this is to be applied to my own types.  
Thanks, will try it.

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [September 11, 2020, 8:52pm UTC](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475/8 "2020-09-11T20:52:05Z")

</div>

> [@joa-quim](#):
>
> I could live with the _ugly_ but the problem is that I would also want `-!, *!, /!, ^! ...`

If you are trying to define in-place versions of elementary operations like `+`, presumably because you are working with large data structures and want to avoid heap allocations, then realize that it is usually _much_ more efficient to combine multiple simple operations in a single “fused” operation (for cache locality and other reasons), so you might want to re-think your approach.

This is precisely the reason for Julia’s fused broadcasting semantics: `@. x = x * y - 3x + 2/z` fuses into a single loop acting in-place on `x` for arrays `x`,`y`,`z`. It is perfectly possible to use this syntax to define “fused” operations on your own types.

---

<div class="post-metadata">

### Author: ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)
#### Post date: [September 11, 2020, 9:27pm UTC](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475/9 "2020-09-11T21:27:31Z")

</div>

Well, this something I would like to offer the users of my package. Broadcasting is nice but so would be !functions but I’m not being able to implement it because I can’t see how to access the elements of `A` & `B` in above example.  
I’ll look at the broadcasting too.

---

<div class="post-metadata">

### Author: ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)
#### Post date: [September 11, 2020, 10:17pm UTC](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475/10 "2020-09-11T22:17:22Z")

</div>

BTW, I’m curious about the `+=` operator. Where is it defined?

---

<div class="post-metadata">

### Author: ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)
#### Post date: [September 11, 2020, 10:34pm UTC](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475/11 "2020-09-11T22:34:34Z")

</div>

It’s not a generic operator. `a += b` is lowered to `a = a + b`, there’s no way to overload that. If you use the broadcasting machinery like @stevengj suggested, you could intercept `a .= ...` and therefore also `a .+= ...` though, through `Base.materialize!` .

---

<div class="post-metadata">

### Author: ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)
#### Post date: [September 11, 2020, 10:54pm UTC](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475/12 "2020-09-11T22:54:49Z")

</div>

The broadcast machinery looks quite complex, and to start with the type in question does not have an `axes` as mentioned necessary

```julia
julia> G1 = mat2grid([0.0 1; 2 3]);

julia> axes(G1)
ERROR: MethodError: no method matching size(::GMT.GMTgrid)

```

---

<div class="post-metadata">

### Author: ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)
#### Post date: [September 11, 2020, 11:27pm UTC](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475/13 "2020-09-11T23:27:57Z")

</div>

Perhaps I’m missing something, but your type looks to me like a special matrix type, so is there a reason why you wouldn’t want to define `size` on it and implement the `AbstractArray` interface for it?

---

<div class="post-metadata">

### Author: ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)
#### Post date: [September 12, 2020, 3:03pm UTC](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475/14 "2020-09-12T15:03:45Z")

</div>

No, nothing against, only ignorance. But again implementing that interface is not obvious. The `Squares` example in the docs is too simplistic. Would I have to declare only [the type](https://github.com/GenericMappingTools/GMT.jl/blob/master/src/gmt_main.jl#L1) as `<: AbstractArray` or do I have to do it also for the array members? But I want some of them to remain `Float64` only.

(and thanks for the advices)

---

<div class="post-metadata">

### Author: ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)
#### Post date: [September 12, 2020, 3:32pm UTC](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475/15 "2020-09-12T15:32:28Z")

</div>

Yes, your type should subtype `AbstractArray{T,N}`, where `T` is the element type and `N` the number of dimensions. It doesn’t matter what types the members of your custom array type are, that’s not important for dispatch. You probably want to implement at least `Base.size` and `Base.getindex`, which should already get you on your way. You can then try doing things like broadcasting, usually you should be able to see from the stacktraces, which additional functions you still need to implement to support a certain feature, but I think there is something in the manual about that as well.

---

<div class="post-metadata">

### Author: ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)
#### Post date: [September 13, 2020, 8:15pm UTC](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475/16 "2020-09-13T20:15:35Z")

</div>

OK, it was not that easy but I finally managed to implement broadcasting. I have more questions but will leave it to another post. I found, however, a strange behavior that even looks like a bug. The implementation is [here](https://github.com/GenericMappingTools/GMT.jl/blob/to-abstArray/src/gmt_main.jl#L1)

This works like expected

```julia
julia> G1 = mat2grid([0.0 pi/4; pi pi/2])
2×2 GMT.GMTgrid{Float64,2}:
 0.0 0.785398
 3.14159 1.5708

julia> G2 = cos.(G1)
2×2 GMT.GMTgrid{Float64,2}:
  1.0 0.707107
 -1.0 6.12323e-17

julia> acos.(G2)
2×2 GMT.GMTgrid{Float64,2}:
 0.0 0.785398
 3.14159 1.5708

julia> cos(G1)
ERROR: MethodError: no method matching exp!(::GMT.GMTgrid{Complex{Float64},2})
Closest candidates are:
  exp!(::StridedArray{T, 2}) where T<:Union{Complex{Float32}, Complex{Float64}, Float32, Float64} at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\LinearAlgebra\src\dense.jl:554
Stacktrace:
 [1] cos(::GMT.GMTgrid{Float64,2}) at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\LinearAlgebra\src\dense.jl:808
 [2] top-level scope at REPL[6]:1

```

but this, which takes quite some time to compute at first time, does not error like the above last case and gives the following result. This is very _dangerous_ because it results from a mistake very easy to make.

```julia
julia> acos(G2)
2×2 Array{Complex{Float64},2}:
 0.651095+5.55112e-17im -0.71526+5.55112e-17im
  1.01153+0.0im 1.66263-2.22045e-16im

```

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [September 16, 2020, 6:37pm UTC](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475/17 "2020-09-16T18:37:20Z")

</div>

> [@joa-quim](#):
>
> does not error like the above last case and gives the following result. This is very _dangerous_ because it results from a mistake very easy to make.

It’s giving you the correct answer — the `acos` of a square matrix is perfectly well defined and that is what it is giving you.

---

<div class="post-metadata">

### Author: ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)
#### Post date: [September 16, 2020, 7:25pm UTC](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475/18 "2020-09-16T19:25:07Z")

</div>

Related: [https://github.com/JuliaArrays/LazyArrays.jl](https://github.com/JuliaArrays/LazyArrays.jl)

---

<div class="post-metadata">

### Author: ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)
#### Post date: [September 16, 2020, 8:15pm UTC](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475/19 "2020-09-16T20:15:23Z")

</div>

It’s not the correct answer. The correct is given by `acos.()`. See, not even the type is correct. And it’s not only `acos`

```julia
julia> G1 = mat2grid([0.0 pi/4; pi pi/2])
2×2 GMT.GMTgrid{Float64,2}:
 0.0 0.785398
 3.14159 1.5708

julia> G2 = cos.(G1)
2×2 GMT.GMTgrid{Float64,2}:
  1.0 0.707107
 -1.0 6.12323e-17

julia> acos.(G2)
2×2 GMT.GMTgrid{Float64,2}:
 0.0 0.785398
 3.14159 1.5708

julia> acos(G2)
2×2 Array{Complex{Float64},2}:
 0.651095+5.55112e-17im -0.71526+5.55112e-17im
  1.01153+0.0im 1.66263-2.22045e-16im

julia> using Statistics

julia> mean.(G1)
2×2 GMT.GMTgrid{Float64,2}:
 0.0 0.785398
 3.14159 1.5708

julia> mean(G1)
1.3744467859455345

julia> std(G1)
1.3413227186681242

```

---

<div class="post-metadata">

### Author: ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)
#### Post date: [September 16, 2020, 8:23pm UTC](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475/20 "2020-09-16T20:23:42Z")

</div>

Steven is referring to [matrix functions](https://en.wikipedia.org/wiki/Matrix_function). Read `?acos(rand(2,2))`.

[Next page](https://discourse.julialang.org/t/is-it-possible-to-define-a-function/46475.md?page=2)
