如何在 Chapel 中保留可接受类型的列表以进行比较
How to keep a list of acceptable types for comparison in Chapel
假设我有 class Student
、BadStudent:Student
、GoodStudent:Student
和 ExcellentStudent: Student
。我想要一个 class 方法只对 Good
和 Exceptional
学生进行操作。类似于:
class AdvancedBasketWeaving {
// this is the question:
var acceptableStudentTypes: [1..2] = [GoodStudent, ExcellentStudent];
proc accept(student: Student) {
for at in this.acceptableStudentTypes {
if student.type == at then return "YES!";
}
return "Computer says 'No'";
}
}
如何获得此功能?
您可以尝试将类型转换为 string
。
例如,
var a = [int: string, string: string];
writeln(a);
var b = 1;
var c = "sdasas";
if b.type: string == a[1] then writeln("This matches!");
if c.type: string != a[1] then writeln("This doesn't match!");
我认为您会希望将两种工具用于此模式:
1) 首先是 Chapel 的 cast 运算符 (:
)。对于 classes,转换类似于 C++ 的动态转换。简而言之,给定一个 class 对象,例如 GoodStudent
的以下实例:
var brian = new GoodStudent();
将对象转换为 class 类型将 return nil
如果对象不是 class 的子class 并且class参考如果是。因此:
...(brian: Student != nil)... // will evaluate to true
...(brian: BadStudent != nil)... // will evaluate to false
...(brian: GoodStudent != nil)... // will evaluate to true
...(brian: ExcellentStudent != nil)... // will evaluate to false
因此,要测试 GoodStudent
或 ExcellentStudent
,您可以这样写:
if (student:GoodStudent != nil || student:ExcellentStudent != nil) then
return "YES!";
或者,如果每个 ExcellentStudent
也是一个 GoodStudent
,您可以考虑将其设为 class 层次结构中 GoodStudent
的子 class 而不是比它的兄弟姐妹。在这种情况下,您可以简单地将条件写为:
if student:GoodStudent != nil then return "YES!";
因为 GoodStudent
和 ExcellentStudent
都会 return 为真。
作为重要说明,可能很容易将此条件写为:
if student.type == GoodStudent
但这不会在您的过程上下文中给出正确的行为,因为它声明如下:
proc accept(student: Student) { ... }
具体来说,.type
查询将 return class 对象的静态(编译时)类型,并且在此例程的上下文中,student
是 Student
由于它的正式类型。所以比较它的静态类型永远不会匹配 GoodStudent
,即使对象的动态类型是 GoodStudent
。使用动态转换通过将静态测试更改为动态测试来解决此问题。另一种方法是使 accept()
过程完全通用,如下所示:
proc accept(student) { ... }
但是随后您通过允许传入其他非Student
类型来打开闸门。
2) 您需要的第二件事(也是您问题的重点)是元组类型,这可能是创建类型集合的最佳/最轻量级方法。 Chapel 仅支持值数组,不支持类型,因此代码中的以下行不合法:
var acceptableStudentTypes: [1..2] = [GoodStudent, ExcellentStudent];
相反,创建一个元组类型来存储您要比较的所有类型:
type acceptableStudentTypes = (GoodStudent, ExcellentStudent);
这引出了我建议的解决方案 (try it online):
class Student {
}
class BadStudent: Student {
}
class GoodStudent: Student {
}
class ExcellentStudent: Student {
}
// a tuple of acceptable types
type acceptableStudentTypes = (GoodStudent, ExcellentStudent);
class AdvancedBasketWeaving {
proc accept(student: Student) {
// iterate over the tuple's size
for param i in 1..acceptableStudentTypes.size do
// see if dynamically casting the student to the type "works"
if student: acceptableStudentTypes(i) != nil then
return "YES!";
return "Computer says 'No'";
}
}
var course = new AdvancedBasketWeaving();
writeln(course.accept(new Student())); // Computer says 'No'
writeln(course.accept(new BadStudent())); // Computer says 'No'
writeln(course.accept(new GoodStudent())); // YES!
writeln(course.accept(new ExcellentStudent())); // YES!
请注意,我已将 acceptableStudentTypes
声明从 class 范围(这是合乎逻辑的,您拥有它的位置)移至模块范围。这是因为我 filed an issue against.
Chapel 中的一个明显错误
或者,如果您可以使 ExcellentStudent
成为 GoodStudent
的子 class,我认为以下内容更好 (try it online):
class Student {
}
class BadStudent: Student {
}
class GoodStudent: Student {
}
class ExcellentStudent: GoodStudent {
}
class AdvancedBasketWeaving {
proc accept(student: Student) {
if student: GoodStudent != nil then
return "YES!";
return "Computer says 'No'";
}
}
var course = new AdvancedBasketWeaving();
writeln(course.accept(new Student())); // Computer says 'No'
writeln(course.accept(new BadStudent())); // Computer says 'No'
writeln(course.accept(new GoodStudent())); // YES!
writeln(course.accept(new ExcellentStudent())); // YES!
假设我有 class Student
、BadStudent:Student
、GoodStudent:Student
和 ExcellentStudent: Student
。我想要一个 class 方法只对 Good
和 Exceptional
学生进行操作。类似于:
class AdvancedBasketWeaving {
// this is the question:
var acceptableStudentTypes: [1..2] = [GoodStudent, ExcellentStudent];
proc accept(student: Student) {
for at in this.acceptableStudentTypes {
if student.type == at then return "YES!";
}
return "Computer says 'No'";
}
}
如何获得此功能?
您可以尝试将类型转换为 string
。
例如,
var a = [int: string, string: string];
writeln(a);
var b = 1;
var c = "sdasas";
if b.type: string == a[1] then writeln("This matches!");
if c.type: string != a[1] then writeln("This doesn't match!");
我认为您会希望将两种工具用于此模式:
1) 首先是 Chapel 的 cast 运算符 (:
)。对于 classes,转换类似于 C++ 的动态转换。简而言之,给定一个 class 对象,例如 GoodStudent
的以下实例:
var brian = new GoodStudent();
将对象转换为 class 类型将 return nil
如果对象不是 class 的子class 并且class参考如果是。因此:
...(brian: Student != nil)... // will evaluate to true
...(brian: BadStudent != nil)... // will evaluate to false
...(brian: GoodStudent != nil)... // will evaluate to true
...(brian: ExcellentStudent != nil)... // will evaluate to false
因此,要测试 GoodStudent
或 ExcellentStudent
,您可以这样写:
if (student:GoodStudent != nil || student:ExcellentStudent != nil) then
return "YES!";
或者,如果每个 ExcellentStudent
也是一个 GoodStudent
,您可以考虑将其设为 class 层次结构中 GoodStudent
的子 class 而不是比它的兄弟姐妹。在这种情况下,您可以简单地将条件写为:
if student:GoodStudent != nil then return "YES!";
因为 GoodStudent
和 ExcellentStudent
都会 return 为真。
作为重要说明,可能很容易将此条件写为:
if student.type == GoodStudent
但这不会在您的过程上下文中给出正确的行为,因为它声明如下:
proc accept(student: Student) { ... }
具体来说,.type
查询将 return class 对象的静态(编译时)类型,并且在此例程的上下文中,student
是 Student
由于它的正式类型。所以比较它的静态类型永远不会匹配 GoodStudent
,即使对象的动态类型是 GoodStudent
。使用动态转换通过将静态测试更改为动态测试来解决此问题。另一种方法是使 accept()
过程完全通用,如下所示:
proc accept(student) { ... }
但是随后您通过允许传入其他非Student
类型来打开闸门。
2) 您需要的第二件事(也是您问题的重点)是元组类型,这可能是创建类型集合的最佳/最轻量级方法。 Chapel 仅支持值数组,不支持类型,因此代码中的以下行不合法:
var acceptableStudentTypes: [1..2] = [GoodStudent, ExcellentStudent];
相反,创建一个元组类型来存储您要比较的所有类型:
type acceptableStudentTypes = (GoodStudent, ExcellentStudent);
这引出了我建议的解决方案 (try it online):
class Student {
}
class BadStudent: Student {
}
class GoodStudent: Student {
}
class ExcellentStudent: Student {
}
// a tuple of acceptable types
type acceptableStudentTypes = (GoodStudent, ExcellentStudent);
class AdvancedBasketWeaving {
proc accept(student: Student) {
// iterate over the tuple's size
for param i in 1..acceptableStudentTypes.size do
// see if dynamically casting the student to the type "works"
if student: acceptableStudentTypes(i) != nil then
return "YES!";
return "Computer says 'No'";
}
}
var course = new AdvancedBasketWeaving();
writeln(course.accept(new Student())); // Computer says 'No'
writeln(course.accept(new BadStudent())); // Computer says 'No'
writeln(course.accept(new GoodStudent())); // YES!
writeln(course.accept(new ExcellentStudent())); // YES!
请注意,我已将 acceptableStudentTypes
声明从 class 范围(这是合乎逻辑的,您拥有它的位置)移至模块范围。这是因为我 filed an issue against.
或者,如果您可以使 ExcellentStudent
成为 GoodStudent
的子 class,我认为以下内容更好 (try it online):
class Student {
}
class BadStudent: Student {
}
class GoodStudent: Student {
}
class ExcellentStudent: GoodStudent {
}
class AdvancedBasketWeaving {
proc accept(student: Student) {
if student: GoodStudent != nil then
return "YES!";
return "Computer says 'No'";
}
}
var course = new AdvancedBasketWeaving();
writeln(course.accept(new Student())); // Computer says 'No'
writeln(course.accept(new BadStudent())); // Computer says 'No'
writeln(course.accept(new GoodStudent())); // YES!
writeln(course.accept(new ExcellentStudent())); // YES!