I think it would be nice to have an overload of the + operator for lists and linked lists that will return a copy that is the result of the second operand being appended to the first one, without changing the contents of the operands (like the + for lists in python).
Something that would allow this:
use List;
var l1: list(int) = [1, 2, 3];
var l2: list(int) = [4, 5, 6];
var l3 = new list(int);
l3 = l1 + l2;
writeln(l3);
writeln(l1);
writeln(l2);
This should output:
[1, 2, 3, 4, 5, 6]
[1, 2, 3]
[4, 5, 6]
By chapel philosophy, the + operator in this case should be promoted to element-wise addition. So, I think that would be more suited as an operator overload.
Also, an extend procedure already exists which appends a list by the elements of another one.
The + operator for element-wise operation would not make sense if the list is of a type that does not have the addition operation defined for it, for example, in case of record types that cannot be "added" per se.
The extend procedure modifies the object on which it is called. What I am proposing, however, is something that would let us have the result of concatenation of the two operands without changing the operands themselves. In the above example, l1 and l2 are unchanged. However, doing l1.extend(l2) would change l1 itself.
What I am proposing can, of course, currently be achieved like this:
...
var l3 = new list(int);
l3.extend(l1);
l3.extend(l2);
...
I believe that using the + operator to do the same would be more intuitive, though.
Doesn't the + operator become possibly confusing when used for lists and arrays at the same time? The following example (in Python) may be a bit artificial, but I am afraid similar confusion might happen even for Chapel (if the meaning of +is extended more and generics are involved).
import numpy as np
a = [1, 2] # python list
b = [3, 4]
print( a + b ) # [1, 2, 3, 4]
print( a + b + a ) # [1, 2, 3, 4, 1, 2]
x = np.array([100, 200]) # numpy ndarray
print( a + x ) # [101, 202]
print( x + a ) # [101, 202]
# print( a + b + x )
# print( (a + b) + x )
# print( x + (a + b) )
# Error: operands could not be broadcast together with shapes (4,) (2,)
print( x + a + b ) # [104 206]
print( a + (b + x) ) # [104 206]
For comparison, some other (statically typed) languages use different symbols for concatenation (like ~ in D and & in Nim), which may be nice to avoid possible confusion.
https://dlang.org/spec/arrays.html#array-concatenation
(TIO)
https://nim-lang.org/docs/sequtils.html (where "seq" is similar to Python list)
(TIO)
Apart from the choice of symbol, I am also wondering whether a function approach (e.g. concat(a, b, c) where concat() takes variadic arguments) might be more efficient than a repeated use of a binary operator (e.g. a ~ b ~ c) if allocation of temporary variables could be done only once.
https://nim-lang.org/docs/sequtils.html#concat%2Cvarargs%5Bseq%5BT%5D%5BT%5D%5D
(TIO)
(this is a bit different but for comparison...)
https://docs.julialang.org/en/v1/base/arrays/#Base.vcat
(TIO)
I agree with @ty1027 . This feature does not bring significant convenience to users but brings confusion and potential performance issues.
For more clarity, I think it would be nice to have some syntax like "a [?] b" (where [?] is some operator for list concatenation) in addition to a function like concat( a, b ). But I am not sure if the symbol [?] = "+" is really a good choice here... (though Python is using it). This is partly because some other languages seem to avoid it, e.g.
https://alvinalexander.com/scala/how-to-merge-concatenate-lists-in-scala-cookbook/
https://stackoverflow.com/a/32135472
Here, I don't think the operator ":::" in the above page is very appealing XD, but the StackOverflow answer above (which mentions type safety) seems to be also useful here.
The operator certainly could be different from +, but I think having some operator or a function like concat() (as suggested by @ty1027) would be quite convenient. That would eliminate any confusion caused by +.
For now, we could go with a concat() defined in the list and LinkedList modules that takes variadic arguments.
LinkedList already has concat method, which is an analog of extend from list. Shouldn't these have the same name extend?
Most helpful comment
Doesn't the
+operator become possibly confusing when used for lists and arrays at the same time? The following example (in Python) may be a bit artificial, but I am afraid similar confusion might happen even for Chapel (if the meaning of+is extended more and generics are involved).For comparison, some other (statically typed) languages use different symbols for concatenation (like
~in D and&in Nim), which may be nice to avoid possible confusion.https://dlang.org/spec/arrays.html#array-concatenation
(TIO)
https://nim-lang.org/docs/sequtils.html (where "seq" is similar to Python list)
(TIO)
Apart from the choice of symbol, I am also wondering whether a function approach (e.g.
concat(a, b, c)whereconcat()takes variadic arguments) might be more efficient than a repeated use of a binary operator (e.g.a ~ b ~ c) if allocation of temporary variables could be done only once.https://nim-lang.org/docs/sequtils.html#concat%2Cvarargs%5Bseq%5BT%5D%5BT%5D%5D
(TIO)
(this is a bit different but for comparison...)
https://docs.julialang.org/en/v1/base/arrays/#Base.vcat
(TIO)