So <>
basically connects two items right?
Hello <> world => Hello world
But whats ++
? can anyone give me an example
So <>
basically connects two items right?
Hello <> world => Hello world
But whats ++
? can anyone give me an example
Helpful resources:
they join text in different quotes
iex(4)> 'hello' ++ 'world'
'helloworld'
iex(5)> "hello" <> "world"
"helloworld"
<>
joins two strings (binaries)
++
joins two lists (including charlists)
Have in mind that there’s a performance penalty for using ++
because it has to fully traverse the first list, from start to end, before doing concatenation. This technique can accumulate surprising amount of slowness in your app if you use it liberally.
Usually it’s preferable to iteratively prepend items to the final desired list (which is an O(1) operation) and Enum.reverse
the list when done.
a <> b
has even worse complexity than a ++ b
as it needs to do a full copy of both sides of the operator for each append. Unless you make sure to trigger the non-copying append optimization. Fortunately copying binary memory is heavily optimized by using memcpy
so it is not noticeable as quickly as when using ++
.
Anyway, when wanting to append binaries, I always try to append them into a list and flatten them when needed (or not at all if they can be passed to the socket unflattened). Example:
## Don't do this
:gen_tcp.send(socket, bin1 <> bin2)
## When you can do this
:gen_tcp.send(socket, [bin1, bin2])
Oh yeah, I always use iolists when the API allows it. Thanks for the extra details.
so <> is better than ++?
Nah, it just depends on the data types you are using.
++
<>
The subtlety in Elixir is that String come in two flavors:
charlist
, which is a list of chars, and is written with simple quotes can be concatenated with ++
: 'hello ' ++ 'world' == 'hello world'
. It’s mainly inherited from Erlang and not used that much in Elixir appsbinaries
which use double-quotes and can be concatenated with <>
: "hello " <> "world" == "hello world"
According to @garazdawi it seems that <>
is potentially worse than ++
. I think both he and @dimitarvp are suggesting that you should try to avoid concatenation calls (especially if it’s a recursive or iterative process). Concatenation and appending to a list is slower than PREpending because of the nature of the data structure. Lists in Elixir are linked lists, which means that to append to the end you have to iterate over the whole list.
See this definition from the Erlang documentation for append (which is what Elixir’s ++
is using under the hood:
append([H|T], Tail) ->
[H|append(T, Tail)];
append([], Tail) ->
Tail.
So the function appending the two lists will have time complexity proportional to the length of the first list argument.