Is it possible to define '+' operator for string as '*' do for them?

I’d like to use ‘+’ operator for string concatenation.
but it is ‘*’ in Julia.

If possible I’d like to define ‘+’ as alias of ‘*’ if opland are strings.
because some insufficient definition cause some side effect.

Thanks in advance!!

No, that would be type piracy. Do not do this!

4 Likes

Of course, you can:

Base.:+(a::String, b::String)=a*b

But there is a clear mathematical reason for the choice in Julia: generally, “+” is considered to be always commutative, while “*” (e.g. for matrices) may be not commutative, and string concatenation is clearly not commutative. Also, yes, this would be type piracy which may render your code harmful if it is used by others.

17 Likes

See also the Julia FAQ: Why does Julia use * for string concatenation? Why not + or something else?

In general, when you learn a new language, you should try to learn the idiomatic “spelling” of things in that language. Trying to write code in Julia that superficially resembles some other language (e.g. Python) is just going to get you into trouble — even if there are no technical issues (ala type piracy), your code won’t fit nicely in to the surrounding ecosystem.

22 Likes

It is however possible to create your own string type with whatever properties you like, without breaking any norms like “type piracy”:

struct MyString <: AbstractString
    s::String
end

macro s_str(e)
    :(MyString($e))
end

Base.getindex(s::MyString, arg::Int) = getindex(s.s, arg)
Base.iterate(s::MyString, state::Int=1) = iterate(s.s, state)
Base.:+(s1::MyString, s2::MyString) = MyString(s1*s2)
Base.:*(n::Integer, s::MyString) = MyString(s.s^n)

julia> s1 = s"string1"
"string1"  # a MyString

julia> s2 = s"string2"
"string2"  # a MyString

julia> s1 + s2
"string1string2"  # also a MyString

julia> 4s1
"string1string1string1string1"

# but, while many operations on Strings work for MyString, they may still return String
# not MyString, unless you handle it specially.

julia> s3 = join((s1,s2), ", ")
"string1, string2"

julia> typeof(s3)
String
5 Likes

It’s even easier to create your own +! No piracy, and you don’t need to forward all the other string methods.

julia> a::String + b::String = a * b  # may need to restart the session for this line to work
+ (generic function with 1 method)

julia> "a" + "b"
"ab"

julia> 2 + 2
ERROR: MethodError: no method matching +(::Int64, ::Int64)
You may have intended to import Base.:+
The function `+` exists, but no method is defined for this combination of argument types.

Closest candidates are:
  +(::String, ::String)
   @ Main REPL[1]:1

Stacktrace:
 [1] top-level scope
   @ REPL[2]:1

julia> a + b = Base.:+(a, b)   # fall back to the Base version
+ (generic function with 2 methods)

julia> 2+2
4

It’s a nice trick for designing DSLs.

In any case, “just use *” is the correct answer of course.

15 Likes

Thank you j-fu for your code and your advice.
I found that your code works well for me.

but “+” looks more natural operator for string concatenation I suppose…

1 Like

Thank you for your suggestion cstjean.
I learned a lot from your code.

I appreciate it!!

Well, but ‘*’ looks strange for me…
thanks anyway

I understand your point.
thank you for your information.
but I am going to use my code for internal use only.

thanks sgaure,
maybe you are genius!
Although I will use j-fu method for now, I might use your method in some other issues.

Take also a look at this thread and the tiny Julia package PlusPlus.jl with just three lines of code.

2 Likes

Another thing is that string concatenation may not be too useful in any language.

Note you can do e.g.:

println(a, b) # and/or use string interpolation

it will be faster than doing concatenation first explicitly: c = a * b first, or c = String(a, b) another possibility if you do not like *, and it’s similar syntax to println, but result can be used generally, and a and b can be strings, or e.g. integers, unlike for *.

Welcome to the Julia community!

2 Likes

59 posts were split to a new topic: The strangeness (or not) of * as string concatenation