我有一个类似下面的脚本。目的是要采用不同的过滤方法来过滤列表。
这里是代码。
2
3 class list_filter {
4 has @.my_list = (1..20);
5
6 method filter($l) { return True; }
7
8 # filter method
9 method filter_lt_10($l) {
10 if ($l > 10) { return False; }
11 return True;
12 }
13
14 # filter method
15 method filter_gt_10($l) {
16 if ($l < 10) { return False; }
17 return True;
18 }
19
20 # expecting a list of (1..10) to be the output here
21 method get_filtered_list_lt_10() {
22 return self.get_filtered_list(&{self.filter_lt_10});
23 }
24
25 # private
26 method get_filtered_list(&filter_method) {
27 my @newlist = ();
28 for @.my_list -> $l {
29 if (&filter_method($l)) { push(@newlist, $l); }
30 }
31 return @newlist;
32 }
33 }
34
35 my $listobj = list_filter.new();
36
37 my @outlist = $listobj.get_filtered_list_lt_10();
38 say @outlist;
期望[1..10]作为此处的输出。但是出现以下错误。
Too few positionals passed; expected 2 arguments but got 1
in method filter_lt_10 at ./b.pl6 line 9
in method get_filtered_list_lt_10 at ./b.pl6 line 22
in block <unit> at ./b.pl6 line 37
我在这里做错了什么?
[在Perl 6中将方法作为参数传递,要么要求您使用MOP(元对象协议)方法,要么按名称传递方法(然后将在运行时为您进行查找)。
但是,如果您实际上没有在这些方法中使用对象做某些事情,为什么还要使用method
?那么,它们也可能是sub
,您can作为参数传递。
也许这是最好的例子:
class list_filter {
has @.my_list = 1..20; # don't need parentheses
sub filter($ --> True) { } # don't need code, signature is enough
# filter sub
sub filter_lt_10($l) { not $l > 10 }
# filter sub
sub filter_gt_10($l) { not $l < 10 }
# private
method !get_filtered_list(&filter_sub) {
@.my_list.grep(&filter_sub);
}
# expecting a list of (1..10) to be the output here
method get_filtered_list_lt_10() {
self!get_filtered_list(&filter_lt_10);
}
}
my $listobj = list_filter.new();
my @outlist = $listobj.get_filtered_list_lt_10();
say @outlist; # [1 2 3 4 5 6 7 8 9 10]
仅返回一个恒定值(在这种情况下为sub filter
)的第一个True
,在带有空主体的签名中更容易表示。
filter_lt_10
和filter_gt_10
子仅需要取反的条件,因此使用not
。
get_filtered_list
方法应该是私有的,因此请在前缀!
之前将其设为私有方法。
在get_filtered_list_lt_10
中,您现在需要使用get_filtered_list
而不是!
来调用.
。然后,通过在filter_lt_10
前面添加&
子作为参数(否则,它将被认为是对没有任何参数的子的调用,否则将失败)。
更改get_filtered_list
以使用内置的grep
方法:这需要一个Callable
块,该块具有单个参数,并且应该返回True
来包含其所处理列表的值。由于sub
带有单个参数is Callable
,因此我们可以直接在其中指定子项。
希望这很有道理。我试图尽可能地接近预期的语义。
[一些一般的编程说明:对我来说,潜艇的命名令人困惑:对我来说,它们应该分别命名为filter_le_10
和filter_ge_10
,因为它们确实是在我看来。另外,如果您确实不想进行任何临时过滤,而只希望从一组特定的预定义过滤器中进行过滤,则最好使用常量或enum
创建一个分配表,并使用该表来指示您想要的过滤器,而不是使用其他要制作和维护的方法的名称来编码此信息。
希望这会有所帮助。
TL; DR您告诉P6在调用filter
方法时需要哪些参数。这样,您在调用约定的参数时就无法通过。因此,P6代表您投诉。要解决该问题,请传递您告诉P6期望的参数,或者停止告诉P6期望它们。 :)
消息说期望的2
,得到的是1
,而不是期望的1
得到的0
。
这是因为self
被隐式传递并添加到消息详细信息的此附加位的“预期”和“获得”总数中,两者都增加了一个。 (此细节可能不及Awesome少,即我们可能应考虑解决的问题。)
当我run your code on tio时得到:
Too few positionals passed; expected 2 arguments but got 1
in method filter at .code.tio line 27
in method print_filtered_list at .code.tio line 12
in block <unit> at .code.tio line 42
第27行的方法[[declaration method filter($l) {...}
告诉P6为每个.filter
方法call期望two自变量:
self
。)我们将其称为argument A。
]$l
参数)。我们称它为[[参数B但是在第12行的&{self.filter}
中,当您为.filter
方法call
argument A,即一个激进的参数时,您没有提供argument B ,即位置参数(after filter
,例如&{self.filter(42)}
)。
Too few positionals passed; expected 2 arguments but got 1
。 3 class list_filter {
4 has @.my_list = (1..20);
5
6 # will be overriding this in derived classes
7 method filter1($l) { return True; }
8 method filter2($l) { return True; }
9
10 # same print method I will be calling from all derived class objects
11 method print_filtered_list($type) {
12 my @outlist = self.get_filtered_list($type);
13 say @outlist;
14 }
15
16 # private
17 method get_filtered_list($type) {
18 my @newlist = ();
19 for @.my_list -> $l {
20 my $f = "filter$type";
21 if (self."$f"($l)) { push(@newlist, $l); }
22 }
23 return @newlist;
24 }
25 }
26
27 class list_filter_lt_10 is list_filter {
28 method filter1($l) {
29 if ($l > 10) { return False; }
30 return True;
31 }
32 method filter2($l) {
33 if ($l > 10) { return False; }
34 if ($l < 5) { return False; }
35 return True;
36 }
37 }
38
39 class list_filter_gt_10 is list_filter {
40 method filter1($l) {
41 if ($l < 10) { return False; }
42 return True;
43 }
44 method filter2($l) {
45 if ($l < 10) { return False; }
46 if ($l > 15) { return False; }
47 return True;
48 }
49 }
50
51 my $listobj1 = list_filter_lt_10.new();
52 $listobj1.print_filtered_list(1);
53 $listobj1.print_filtered_list(2);
54
55 my $listobj2 = list_filter_gt_10.new();
56 $listobj2.print_filtered_list(1);
57 $listobj2.print_filtered_list(2);
58
输出:
./b.pl6
[1 2 3 4 5 6 7 8 9 10]
[5 6 7 8 9 10]
[10 11 12 13 14 15 16 17 18 19 20]
[10 11 12 13 14 15]
obj.^lookup(method name)
,并通过传入对象本身(通常为“ self”)作为第一个参数,然后传入其他参数来调用它。要将对象绑定到该函数,以便不必每次都显式添加该对象,请使用assuming函数。class MyClass {
method log(Str $message) { say now ~ " $message"; }
method get-logger() { return self.^lookup('log').assuming(self); }
}
my &log = MyClass.get-logger();
log('hello'); # output: Instant:1515047449.201730 hello