如何将正则表达式作为参数传递给 Perl 6 中的子例程

How to pass regex as an argument to subroutine in Perl 6

可能我做的事情完全错了,但是有什么方法可以使用子程序修改和组合 regexes 吗?下面的程序无法编译。

sub a(Regex $r1) {
  return rx/ <$r1> a /
}

my regex letter_b { b };

my $new = a(letter_b);
say $new;

查看 Regex 的文档,上面写着:

A named regex can be defined with the regex declarator followed by its definition in curly braces. Since any regex does Callable introspection requires referencing via &-sigil.

my regex R { \N };
say &R.^name; # OUTPUT: «Regex␤»

此外,Grammar 文档(对于概念,而不是类型),它对此进行了更多解释:

The main ingredient of grammars is named regexes. While the syntax of Perl 6 Regexes is outside the scope of this document, named regexes have a special syntax, similar to subroutine definitions:

my regex number { \d+ [ \. \d+ ]? }

In this case, we have to specify that the regex is lexically scoped using the my keyword, because named regexes are normally used within grammars.

Being named gives us the advantage of being able to easily reuse the regex elsewhere:

say so "32.51" ~~ &number;                                    # OUTPUT: «True␤»
say so "15 + 4.5" ~~ / <number> \s* '+' \s* <number> /        # OUTPUT: «True␤»

因此,要将命名的正则表达式作为参数传递到 a 子例程中,您所要做的就是在其前面加上一个符号:

my $new = a(&letter_b);
#           ^
#  This is what you need!

say $new;
say so "ba" ~~ $new;         # OUTPUT: «True␤»
say so "ca" ~~ $new;         # OUTPUT: «False␤»

从@callyalater 的结论开始[1]:

my $new = a(&letter_b);
#           ^
#  This is what you need!

在这个答案的其余部分,我将解决两个后续问题,我认为如果@callyalater 的答案对他们不起作用,人们可能仍然会遇到这些问题。

  • 为什么?

  • 错误信息是怎么回事?

为什么?

几乎所有编程语言都有命名函数,您可以声明一次,然后调用任意次。许多人支持functions as first class values。乐呢。这意味着 raku 允许您以两种根本不同的方式引用已声明的函数:

  • "call" a function,写下它的名字。它会积极地做它声明要做的事情。

  • 要将 "refer" 作为第一个 class 值添加到函数中,请在前面加上 &。引用将被被动传递。

因此:

sub foo { say 42 }
say foo; # 42
say &foo # &foo

在我继续之前,我必须注意,当用英语或任何人类语言写这些东西时,事情会变得有点棘手。首先,根据英语的定义,如果我们写 anything 那么我们指的是它!此外,英语实际上不能 "call" foo。所以约定是只写 foo 当上下文应该很明显我们是说调用它(在 raku 中,foo)还是只是 "referring" 到它(在 raku 中,&foo).

与其他语言不同,在 raku 中正则表达式是函数。在以下代码的第二行中,letter_b 调用 ,而不仅仅是被引用:

my regex letter_b { b }
letter_b

所以在 my $new = a(letter_b); 中,正则表达式 letter_b 调用 ,并且 该调用的结果 将传递给 a 的调用,而在 my $new = a(&letter_b); 中,您只是传递 letter_b.

的引用

错误信息是怎么回事?

Too few positionals passed; expected 1 argument but got 0␤

乐库中有几个 class 函数。一个是 Regex. The Regex class is a sub-class of Method:

my regex foo { ... }
say &foo ~~ Method; # True
my method bar { ... }
say &bar ~~ Method; # True

如果在没有调用者的情况下调用方法 bar 会发生什么情况?:

bar # Too few positionals passed; expected 1 argument but got 0 

这就是为什么如果您在没有 argument/invocant 的情况下调用 letter_b 会收到该错误消息的原因。

(如果您在语法中声明一个方法,它会自动获取语法 class/object 作为它的调用者;记住语法是 classes。)

脚注

[1] 如果在我写完很久之后有人点赞,我经常会查看我的答案。刚刚有人做了。如果我发现一种方法可以提高我们 comments/answers 的集体实用性,例如通过删除或编辑我的问题,我会这样做,有时会重写它作为相对于已接受答案的评论。