# How about direct sum ⊕ as vector attach operator?

## Background

I know that Julia’s design is very reasonable, especially from the viewpoint of mathematics; it’s my favorite feature of Julia. For example, Julia uses * as a string join operator instead of +, unlike many programming languages, because it makes sense in the context of (abstract) algebra:

\text{"hello"} \ast \text{"world"} = \text{"helloworld"}

is much more natural than

\text{"hello"} + \text{"world"} = \text{"helloworld"}

obviously. But sometimes I miss some operators in Python. In this context, + serves as a vector concatenator.

Python 3.11.4 (tags/v3.11.4:d2340ef, Jun  7 2023, 05:45:37) [MSC v.1934 64 bit (AMD64)] on win32
>>> x = [1,2]
>>> y = [3,4]
>>> x + y
[1, 2, 3, 4]


Of course, I think vcat(x, y) or [x; y] in Julia are also great.

julia> x = [1,2]
2-element Vector{Int64}:
1
2

julia> y = [3,4]
2-element Vector{Int64}:
3
4

julia> vcat(x, y)
4-element Vector{Int64}:
1
2
3
4

julia> [x; y]
4-element Vector{Int64}:
1
2
3
4


I understand that this grammatical consistency is important for reading or writing code. Most significantly, I know that x + y is totally weird in a mathematical sense.

Then how about \oplus? Usually, in general mathematics, a direct sum \oplus (\oplus) refers to a Cartesian product of vector space or some algebraic structures. For instance, the plane \mathbb{R}^{2} and the z-axis \mathbb{R}^{1} could be merged in 3-dimensional space \mathbb{R}^{3} by \mathbb{R}^{3} = \mathbb{R}^{2} \oplus \mathbb{R}^{1}. In a coordinate system, it’s exactly the same as vector concatenation, (x, y, z) = (x, y) \oplus (z).

## Implementation

Below are simple implementations. If you love these, you can use them personally even if Julia doesn’t change. I believe all of you guys have a personal library, just for yourselves.

### Binary operation

Please note that I didn’t check for performance issues. vcat or other ways could be more efficient and fast.

julia> ⊕(x, y) = [x; y]
⊕ (generic function with 1 method)

julia> [1, 2] ⊕ [3, 4]
4-element Vector{Int64}:
1
2
3
4


### \bigoplus_{k} A_{k}

Since \oplus is a binary operation, we can generalize it using reduce.

julia> reduce(⊕, [[1, 2], [3, 4], [5, 6, 7]])
7-element Vector{Int64}:
1
2
3
4
5
6
7


The following is a method form.

julia> ⊕(x, y...) = reduce(⊕, [x, y...])
⊕ (generic function with 2 methods)

julia> ⊕([1, 2], [3, 4], [5, 6, 7])
7-element Vector{Int64}:
1
2
3
4
5
6
7


### Clean code

⊕(x, y) = [x; y]
⊕(x, y...) = reduce(⊕, [x, y...])


2 Likes

You can of course introduce this definition for the operator in your own code or package, but adding it to Julia Base is likely not a good idea, at least not as an exported symbol. Doing so would break most code that already defines this operator for themselves. Here’s a list of registered packages that already make use of this operator:
https://juliahub.com/ui/Search?q=⊕&type=symbols

9 Likes

Base is allowed to export new names; it won’t break any code that defines or imports this operator, only code where there is ambiguity.

⊕ seems fine if that’s what it means — are there other mathematical usages of ⊕ that would conflict with this meaning?

Looking through the other languages, I see infix operators:

,
++
∾
+
~
&
@
|||
<<


of which Julia has available

++
∾
~
@
|||


It would be nice to even have a function to concatenate sequences. vcat maybe should’ve been that but it does weird stuff a lot of the time.

julia> vcat("a", "b")
2-element Vector{String}:
"a"
"b"


I’d be happy enough with an append or concat.

1 Like
1 Like

Even if “base is allowed to export new names”, it might not be a good idea and in the best interest of the users of the language.

And it does break importing code

julia> module Foo
export sin
sin(x) = 0
end
Main.Foo

julia> using .Foo

julia> sin(2)
WARNING: both Foo and Base export "sin"; uses of it in module Main must be qualified
ERROR: UndefVarError: sin not defined
Stacktrace:
[1] top-level scope
@ REPL[3]:1


That’s the ambiguous case. The unambiguous case is

julia> module Foo
export sin
sin(x) = 0
end
Main.Foo

julia> using .Foo: sin

julia> sin(2)
0

2 Likes
3 Likes