Search code examples
tuplesconcatenationadditionhpcchapel

Tuple Concatenation in Chapel


Let's say I'm generating tuples and I want to concatenate them as they come. How do I do this? The following does element-wise addition:

if ts = ("foo", "cat"), t = ("bar", "dog")

ts += t gives ts = ("foobar", "catdog"),

but what I really want is ts = (("foo","cat"),("bar","dog")).

So I guess the first question is "does Chapel support tuple concatention?", then "is there a binary operator/function for it?", then "if not, what is a good way to do it?", and lastly "make my life easier if you know a better way of living".

Please address the questions in order.

I appreciate the help!!


Solution

  • the first question is "does Chapel support tuple concatention?"

    I believe the answer here is "no" for the following reason: (1) A Chapel variable has a single static type that cannot change over its lifetime, and (2) a tuple's type is defined as its static number of elements as well as the type of each element. Thus, given your variable ts

    ts = ("foo", "cat")
    

    its type is 2*string ("a 2-tuple of strings") and this would prevent it from ever being able to store the value (("foo","cat"),("bar","dog")) since its type is 2*(2*string) ("a 2-tuple of 2-tuples of strings"). So while these two tuples have the same number of elements (2), they differ in their element types ("string" vs. "2-tuple of string") and therefore aren't the same type (aren't compatible).

    "is there a binary operator/function for it?"

    Due to the above, no.

    then "if not, what is a good way to do it?"

    A few things come to mind, but may or may not be helpful depending on your specific situation. Rather than trying to re-assign ts, you could create a new tuple that was a tuple-of-tuples:

    const ts2 = (ts, t);
    

    and you could even do this recursively in a routine, though that would likely end up blowing up your code size if the tuple grew to any significant length (because each call to the function would generate a tuple of a different type and unique code for it).

    From what I'm seeing in your question, I think you may want to use a list of tuples or a 1D array (vector) of tuples. Here's a list-based approach:

    use List;
    
    var listOfTups: list(2*string);
    
    listOfTups.append(("foo", "cat"));
    listOfTups.append(("bar", "dog"));
    
    writeln(listOfTups);
    

    And here's an array-based approach:

    var arrOfTups: [1..0] 2*string;
    
    arrOfTups.push_back(("foo", "cat"));
    arrOfTups.push_back(("bar", "dog"));
    
    writeln(arrOfTups);
    

    Of the two, I would recommend the array-based approach because arrays are much more first-class and powerful in Chapel (they enjoy syntactic support, permit data parallelism, support promotion of scalar functions and operators, etc.) whereas lists are just a convenience library.

    and lastly "make my life easier if you know a better way of living".

    One other related thing I can think of to mention if you're not aware of it is that "varargs" functions in Chapel effectively convert those arguments to tuples. So given:

    proc myFunc(x...) {
      writeln(x.type:string);
    }
    
    myFunc(("foo", "cat"), ("bar", "dog"));
    

    the output is:

    2*2*string