Chapel 中的元组串联

6
假设我正在生成元组,并且想要在它们到来时将它们连接起来。我该怎么做?以下代码执行逐个元素相加:
如果 `ts = ("foo", "cat")`,`t = ("bar", "dog")`
`ts += t` 得到 `ts = ("foobar", "catdog")`,
但我真正想要的是 `ts = (("foo","cat"),("bar","dog"))`。
所以我想问的第一个问题是“Chapel是否支持元组连接?”,然后是“是否有二元运算符/函数可用于此操作?”,接着是“如果没有,有什么好的方法可以实现?” 最后,“如果您知道更好的方法,请让我的生活更轻松”。
请按顺序回答这些问题。
非常感谢您的帮助!

就我个人而言,我认为将这个问题的名称从“元组加法”更改为“元组连接”可能会使标题更加精确和易于搜索,但如果您不同意,我也不急于更改它。 - Brad
1
@Brad 是的,没错 - Tshimanga
1个回答

6

第一个问题是“Chapel是否支持元组连接?”

我认为答案是“不支持”,原因如下:(1) Chapel变量具有单一静态类型,其生命周期内不能更改;(2) 元组的类型定义为其静态元素数量以及每个元素的类型。因此,考虑到您的变量ts

ts = ("foo", "cat")

它的类型是2*string(“两个字符串的二元组”),这将阻止它存储值(("foo","cat"),("bar","dog")),因为的类型是2*(2*string)(“两个二元组的二元组字符串”)。因此,尽管这两个元组具有相同数量的元素(2),但它们的元素类型不同(“字符串”与“二元组字符串”),因此它们不是相同类型(不兼容)。

“是否有二进制运算符/函数?”

由于上述原因,不可行。

那么“如果没有,有什么好方法可以实现?”

有几件事情可以考虑,但可能根据您的具体情况而有所帮助或不帮助。而不是试图重新分配ts,可以创建一个新的元组,该元组是元组的元组。
const ts2 = (ts, t);

你甚至可以在一个程序中递归地执行此操作,虽然如果元组变得足够长的话,这可能会导致代码膨胀(因为每次函数调用都会生成一个不同类型和独特代码的元组)。
从你问题描述中所看到的,我认为你可能希望使用一个元组列表或一维数组(向量)的元组。以下是基于列表的方法:
use List;

var listOfTups: list(2*string);

listOfTups.append(("foo", "cat"));
listOfTups.append(("bar", "dog"));

writeln(listOfTups);

以下是基于数组的方法:

var arrOfTups: [1..0] 2*string;

arrOfTups.push_back(("foo", "cat"));
arrOfTups.push_back(("bar", "dog"));

writeln(arrOfTups);

在这两种方法中,我推荐使用基于数组的方法,因为在 Chapel 中数组更加强大和优秀(它们具有语法支持,允许数据并行处理,支持标量函数和运算符的提升等等),而列表只是一个方便的库。

最后,“如果你知道更好的生活方式,请让我的生活变得更轻松”。

如果您不知道,还有一件相关的事情可以提一下,那就是 Chapel 中的“varargs”函数会将这些参数转换为元组。所以有了:

proc myFunc(x...) {
  writeln(x.type:string);
}

myFunc(("foo", "cat"), ("bar", "dog"));

输出结果为:
2*2*string

是的,这正是我所想的。同样地,在Haskell中,元组是固定长度的,但我曾听说过有一个附加项以及CDO包的.execute()方法,用于将嵌套元组而不是元组数组传递给postgres,因此我认为Chapel可能在某些新手不会立即了解的隐藏魔法方面有所发展。@Brad - Tshimanga
顺便说一句,谢谢你这么快回复。我很感激 :) @Brad - Tshimanga
不用谢。我对CDO包及其接口一点也不熟悉...我想知道是否可以添加额外的.execute()重载,以接受元组数组?这可能值得针对该包提出功能请求问题? - Brad
是的,我正在考虑fork它并提交一个PR。 - Tshimanga

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接