我有一个像下面的脚本。 目的是使不同的过滤器的方法来筛选列表。
下面是代码。
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
当时的,它可以作为参数传递。
也许,这就是最好的例子:
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
取一个参数是 Callable
,我们就可以有直接指定子。
希望这是有意义的。 我试图保持尽可能接近到预期的语义。
一些通用的编程备注:感觉对我来说,潜艇的命名是混乱:感觉对我来说,他们应该被称为filter_le_10
和filter_ge_10
,因为这是真的,他们做什么,在我看来。 此外,如果你真的不想要任何的ad-hoc过滤,而是从一组特定的预定义过滤器的过滤只,你很可能会通过创建一个使用常数或调度表更好enum
S,并用它来指示哪个过滤器你想要的,而不是编码另一种方法来制作,维护的名称信息。
希望这可以帮助。
TL; DR你告诉P6呼唤你的时候会发生什么参数filter
方法。 然后你未能通过商定的参数(S),当你打电话吧。 所以P6抱怨代为通知。 为了解决这个问题,可以传递参数()你告诉P6期待或停止告诉P6指望他们。 :)
有消息称预计2
,拿到了1
,而不是预期的1
得到0
。
这是因为self
被隐,并加入到了“预期”和“得到”总计在消息细节这一附加位,由一个碰撞均上涨。 (这个细节可能比真棒少,即是我们或许应该考虑固定。)
当我在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
该方法声明 method filter($l) {...}
在第27行告诉P6期待每个有两个参数.filter
方法调用 :
但在&{self.filter}
管线12,而你提供.filter
与一个参数的方法的呼叫 ,即,调用者参数,您没有提供一个参数B,即一个位置参数( 后 filter
,例如&{self.filter(42)}
)。
因此Too few positionals passed; expected 2 arguments but got 1
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]
在&{self.method}
语法是新的我,所以感谢。 不幸的是,如果需要的参数不工作。 您可以使用sub
如提到的其他海报,但如果你需要使用的方法,你可以通过调用获取方法self.^lookup
,它是利用伊丽莎白提到的元对象协议。 (“^”是指你不打电话就是这样类的一部分,而是其中包含主类的胆量/实施细则“影子”类的一部分的方法。)
为了得到一个方法,用跑obj.^lookup(method name)
,并通过在对象本身传递(经常“自我”)作为第一个参数,那么其他的参数调用它。 要将对象绑定到功能,所以它不需要每次都明确添加,使用假设功能。
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
文章来源: how to pass a class method as argument to another method of the class in perl 6