最近与 Brad Chamberlain, Steve Deitz讨论这个问题,在其中要推导还是比较麻烦的。
问题的引入是我在Chapel中编写了一个程序:
def sum(args:int ...?n)
{
var res : int;
for i in 1..n { res += args[i]; }
return res;
}
writeln(sum(1,2,3,4,5,6,7,8,9));
这是正确的,而下面这个:
def sum(args:?t ...?n)
{
var res : t;
for i in 1..n { res += args[i]; }
return res;
}
writeln(sum(1,2,3,4,5,6,7,8,9));
不对,因为在下面这个程序中t被解释成了9*int。
这里丧失了一致性。
Steve给出的一个方案是使用where clause:
def writeDefaultValues(args:?t ...?n) where n*t(1) == t {
def writeDefaultValues(args:?t ...?n) where n*t(1) != t {
说明t的属性(同类tuple还是异类的),能够解决编程问题。但没有解决一致性的问题。
Brad考虑修改这种函数的声明,提出了如下方案(以下是引用其原文):
I'd forgotten about the heterogeneous case -- for the second example sent in, I think that this argues for the type ?t to refer to the tuple of arguments as a whole rather than simply 'int'. This suggests to me that the first example is the one that's inconsistent:
def sum(args:int ...?n) {
in that 'int' doesn't describe the full set of types of args, but only a single one. Changing this to:
def sum(args:?n*int ...) {
and/or:
def sum(args:?n*int ...n) {
seems more consistent as a way of specifying that args is a homogenous set of integers rather than using a single scalar type as in the first prototype above. This would also permit one to express that all of args are the same unspecified type using:
def sum(args:?n*?t ...) {
and/or:
def sum(args:?n*?t ...n) {
While this does impose a constraint on the types that can be sent to sum(), in this form the constraint comes more from the presence of the * in the type signature (indicating a homogenous tuple) rather than the presence of the queries themselves. I.e., not inconsistent with things like [] constraining an argument to be an array.
[Steve, maybe this is what you were suggesting in your mail -- it wasn't entirely clear to me how you were proposing to handle the apparent inconsistency.]
In this scheme, presumably:
def sum(args:int ... ?n) {
would be illegal because the type of args would have to be a tuple type since it's a varargs argument.
结果Steve发现了问题(引用):
If think it is more natural to interpret
def bar(args: int...) {
as defining a function that takes a variable number of integers and
def bar(arg: ?n*int) {
as defining a function that takes a tuple of integers where n is the number of components in the tuple, thus leading to
def bar(arg: ?n*int...) {
as defining a function that takes a variable number of n-tuple of integers.
最后一句真是精辟!怎么区分输入的参数是n个int还是 ? 个int tuple呢?没什么好办法:(
最后的解决方案似乎是(from steve):
In answer to the question below, that's right, I mean just no queries on the components. We can still query the number of arguments as
def bar(arg ... ?n) {
结果是不允许大家做type query了...不知道这会不会在chapel 1.0中体现(也许到那时会有更好的办法呢...)