# Extend \`Base.+\` but don't export it by default

**URL:** https://discourse.julialang.org/t/extend-base-but-dont-export-it-by-default/1282
**Category:** General Usage
**Created:** [January 4, 2017, 3:27pm UTC](https://discourse.julialang.org/t/extend-base-but-dont-export-it-by-default/1282 "2017-01-04T15:27:27Z")
**Posts on this page:** 16
**Page:** 1

<div class="post-metadata">

### Author: ![dfdx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dfdx/32/120_2.png) [@dfdx](https://discourse.julialang.org/u/dfdx)
#### Post date: [January 4, 2017, 3:27pm UTC](https://discourse.julialang.org/t/extend-base-but-dont-export-it-by-default/1282/1 "2017-01-04T15:27:27Z")

</div>

In my module `A` I have defined `+` for symbols.

```julia
julia> module A 
           import Base: +

           +(x::Symbol, y::Symbol) = :(+($x, $y))
       end
A

```

I would like to use it in some module `B`, but since adding 2 symbols might be error prone, I don’t want it to be exported to other modules. Yet, since `+(::Symbol, ::Symbol)` extends `Base.+`, it becomes automatically available to all modules whenever `A` is loaded. E.g. in REPL / `Main` module:

```julia
julia> :x + :y
:(x + y)

```

Is there a way to define `+(::Symbol, ::Symbol)`, but keep it private unless explicitly imported?

---

<div class="post-metadata">

### Author: ![tkelman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkelman/32/692_2.png) [@tkelman](https://discourse.julialang.org/u/tkelman)
#### Post date: [January 4, 2017, 3:36pm UTC](https://discourse.julialang.org/t/extend-base-but-dont-export-it-by-default/1282/2 "2017-01-04T15:36:17Z")

</div>

No. Base has one set of method tables for +, and all other modules that use Base’s + will see any changes you make to it. That’s why this practice is known as “type piracy” and is discouraged. Extending methods of another module’s generic function on a type signature which is all types from other modules can change the behavior of unrelated code when your module is loaded. Either use a different function/operator name, or one that’s not imported from another module, or make sure at least one of the types in the signatures you extend are types you’ve defined in your own module. You could make a simple wrapper type around Symbol to avoid changing the behavior of other code.

---

<div class="post-metadata">

### Author: ![simonbyrne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simonbyrne/32/19_2.png) [@simonbyrne](https://discourse.julialang.org/u/simonbyrne)
#### Post date: [January 4, 2017, 4:06pm UTC](https://discourse.julialang.org/t/extend-base-but-dont-export-it-by-default/1282/3 "2017-01-04T16:06:15Z")

</div>

We should add a type piracy section to [the style guide](http://docs.julialang.org/en/release-0.5/manual/style-guide/).

---

<div class="post-metadata">

### Author: ![dfdx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dfdx/32/120_2.png) [@dfdx](https://discourse.julialang.org/u/dfdx)
#### Post date: [January 4, 2017, 4:42pm UTC](https://discourse.julialang.org/t/extend-base-but-dont-export-it-by-default/1282/4 "2017-01-04T16:42:40Z")

</div>

Fair enough. Then a follow up question: what other operators can be defined? I noticed that, for example:

```
++
ˆˆ

```

aren’t defined in base, but can be defined in user module, while:

```
**
--

```

aren’t defined and are considered invalid operators.

So is there a table of available operators or some rules to find them?

---

<div class="post-metadata">

### Author: ![tkelman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkelman/32/692_2.png) [@tkelman](https://discourse.julialang.org/u/tkelman)
#### Post date: [January 4, 2017, 4:45pm UTC](https://discourse.julialang.org/t/extend-base-but-dont-export-it-by-default/1282/5 "2017-01-04T16:45:13Z")

</div>

I believe that list is here: [https://github.com/JuliaLang/julia/blob/7eadb55e2d43edad1fc79adf0eb01d975562880d/src/julia-parser.scm#L9-L30](https://github.com/JuliaLang/julia/blob/7eadb55e2d43edad1fc79adf0eb01d975562880d/src/julia-parser.scm#L9-L30)

---

<div class="post-metadata">

### Author: ![Evizero](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/evizero/32/10118_2.png) [@Evizero](https://discourse.julialang.org/u/Evizero)
#### Post date: [January 4, 2017, 4:46pm UTC](https://discourse.julialang.org/t/extend-base-but-dont-export-it-by-default/1282/6 "2017-01-04T16:46:32Z")

</div>

`\oplus` may work for you. It seems free.

```julia
julia> ⊕
ERROR: UndefVarError: ⊕ not defined

julia> ⊕(x::Symbol, y::Symbol) = :(+($x, $y))
⊕ (generic function with 1 method)

julia> :a ⊕ :b
:(a + b)

```

---

<div class="post-metadata">

### Author: ![dfdx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dfdx/32/120_2.png) [@dfdx](https://discourse.julialang.org/u/dfdx)
#### Post date: [January 4, 2017, 5:14pm UTC](https://discourse.julialang.org/t/extend-base-but-dont-export-it-by-default/1282/7 "2017-01-04T17:14:35Z")

</div>

Love it! Thanks!

For reference, ⊗ (`\otimes`), as well as dotted versions .⊕ and .⊗, are also available for definition.

---

<div class="post-metadata">

### Author: ![Evizero](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/evizero/32/10118_2.png) [@Evizero](https://discourse.julialang.org/u/Evizero)
#### Post date: [January 4, 2017, 5:17pm UTC](https://discourse.julialang.org/t/extend-base-but-dont-export-it-by-default/1282/8 "2017-01-04T17:17:25Z")

</div>

> [@dfdx](#):
>
> as well as dotted versions .⊕ and .⊗, are also available for definition

Not needed on current master

```julia
julia> ⊕(x::Symbol, y::Symbol) = :(+($x, $y))
⊕ (generic function with 1 method)

julia> :a ⊕ :b
:(a + b)

julia> [:a,:c] .⊕ [:b,:d]
2-element Array{Expr,1}:
 :(a + b)
 :(c + d)

```

---

<div class="post-metadata">

### Author: ![dfdx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dfdx/32/120_2.png) [@dfdx](https://discourse.julialang.org/u/dfdx)
#### Post date: [January 4, 2017, 5:41pm UTC](https://discourse.julialang.org/t/extend-base-but-dont-export-it-by-default/1282/9 "2017-01-04T17:41:49Z")

</div>

In my case I need a bit different definition:

```
.⊕(x::Symbol, y::Symbol) = :($x .+ $y)

```

This might be inconsistent with general broadcasting rules, so that’s why I try to keep such things private to my module.

---

<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: [January 4, 2017, 6:19pm UTC](https://discourse.julialang.org/t/extend-base-but-dont-export-it-by-default/1282/10 "2017-01-04T18:19:53Z")

</div>

> [@dfdx](#):
>
> `.⊕(x::Symbol, y::Symbol) = :($x .+ $y)`

While it is possible to define this in 0.6 with

```julia
Base.broadcast(::typeof(⊕), x::Symbol, y::Symbol) = :($x .+ $y)

```

I wouldn’t recommend it. The problem is that this method will not get called in various cases, e.g. if you combine it with other dot operations, due to loop fusion. Even if you just do `(:x .⊕ :y) .⊕ :z`, it will fuse into `broadcast((x,y,z) -> (x ⊕ y) ⊕ z, :x, :y, :z)`.

Basically, in 0.6 you shouldn’t be thinking of `.⊕` or `.+` as operators by themselves, but rather as syntactic sugar for a (fusing) broadcast call.

---

<div class="post-metadata">

### Author: ![dfdx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dfdx/32/120_2.png) [@dfdx](https://discourse.julialang.org/u/dfdx)
#### Post date: [January 4, 2017, 8:43pm UTC](https://discourse.julialang.org/t/extend-base-but-dont-export-it-by-default/1282/11 "2017-01-04T20:43:14Z")

</div>

Ah, intersting. Will it still be possible to manually construct expression like `:((x .⊕ y) .⊕ z)` or `:((x .+ y) .+ z)`?

---

<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: [January 4, 2017, 10:03pm UTC](https://discourse.julialang.org/t/extend-base-but-dont-export-it-by-default/1282/12 "2017-01-04T22:03:37Z")

</div>

Yes, expressions involving dot operators are still valid expressions and parse just fine. They get converted to `broadcast` calls during lowering.

---

<div class="post-metadata">

### Author: ![MikeInnes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikeinnes/32/3656_2.png) [@MikeInnes](https://discourse.julialang.org/u/MikeInnes)
#### Post date: [January 4, 2017, 11:18pm UTC](https://discourse.julialang.org/t/extend-base-but-dont-export-it-by-default/1282/13 "2017-01-04T23:18:46Z")

</div>

Actually, this _is_ possible, and even very easy:

```julia
module A
  +(args...) = Base.:+(args...)
  x::Symbol + y::Symbol = :(+($x, $y))
end

module B
  import Main.A: +
  @show :a + :b #> :(a+b)
  @show 1 + 2 #> 3
end

:a + :b # Error

```

---

<div class="post-metadata">

### Author: ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)
#### Post date: [January 5, 2017, 12:56am UTC](https://discourse.julialang.org/t/extend-base-but-dont-export-it-by-default/1282/14 "2017-01-05T00:56:01Z")

</div>

There are no possible performance problems with having to go through the Vararg function to reach the Base one?

---

<div class="post-metadata">

### Author: ![nsmith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsmith/32/979_2.png) [@nsmith](https://discourse.julialang.org/u/nsmith)
#### Post date: [January 5, 2017, 5:59am UTC](https://discourse.julialang.org/t/extend-base-but-dont-export-it-by-default/1282/15 "2017-01-05T05:59:06Z")

</div>

That is pretty slick @MikeInnes. Could you explain the difference between

`+(args...) = Base.+(args...)`

and,

`+(args...) = Base.:+(args...)`?

I’ve never seen that second idiom before and my playing around in the repl with your example points to that being important for this thing to work.

---

<div class="post-metadata">

### Author: ![MikeInnes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikeinnes/32/3656_2.png) [@MikeInnes](https://discourse.julialang.org/u/MikeInnes)
#### Post date: [January 5, 2017, 11:24am UTC](https://discourse.julialang.org/t/extend-base-but-dont-export-it-by-default/1282/16 "2017-01-05T11:24:47Z")

</div>

@kristoffer.carlsson correct. In any case where `Base.:+` would have been statically resolved, it’s easy for the compiler to inline `A.:+`, effectively eliding it completely. Forwarding functions like this sometimes runs the risk of overloading the inlining heuristic, but that’s easy to avoid with an `@inline` annotation.

@nsmith `Base.:fft` is the same as `Base.fft`, i.e. it gets that named object from another module. With operators `Base.+` doesn’t work (I assume because it’s ambiguous with broadcast operators like `x.+y`) so the colon version is required.
