内省捕获的更好方法

Ric*_*rth 5 introspection raku

我想测试签名中第一个对象的类型。下面显示了我发现的一些方法。但是为什么对 Type(下面 3 个测试中的第 2 个)的智能匹配不起作用?有没有比字符串化和测试 Type 的字符串等价物更好的方法?(以下是我正在研究的用例)

raku -e "sub a( |c ) { say so |c[0].WHAT.raku ~~ /'Rat'/, so |c[0].WHAT ~~ Rat, so |c[0].^name ~~ /'Rat'/ };a(3/2);a(2)"
TrueFalseTrue
FalseFalseFalse
# OUTPUT:
#TrueFalseTrue
#FalseFalseFalse
Run Code Online (Sandbox Code Playgroud)

我正在写一个proto sub handle,大多数潜艇都有类似的签名,例如。multi sub handle( Pod $node, MyObj $p, Int $level --> Str)

所以大多数多子节点根据 $node 中的内容做不同的事情。但是,如何处理handle使用Nil或纯字符串调用的情况。我正在考虑类似的事情

proto handle(|c) {
    if |c[0].^name ~~ /'Str'/ { # code for string }
    else { {*} }
}
Run Code Online (Sandbox Code Playgroud)

rai*_*iph 7

一种更好的内省方式......

一般来说,在任何编程语言中做任何事情的更好方法是如果可以避免它就不要内省。

一般来说,在乐,你避免人工反省。有关进一步讨论,请参阅本答案末尾的自省部分。

...捕获

获得捕获内省提供的功能的最佳工具是使用签名。这是他们人生的主要目的。

我想测试签名中第一个对象的类型

使用签名:

proto handle(|) {*}
multi handle( Pod $node )   { ... }
multi handle( Str $string ) { ... }
multi handle( Nil )         { ... }
Run Code Online (Sandbox Code Playgroud)

下面显示了我发现的一些方法。

当他们做你想做的事时,他们基本上忽略了 Raku 的所有标志性功能。它们将签名简化为作为单个结构的捕获的绑定;然后在例程的主体中使用该捕获的手动内省。

使用签名几乎总是有一种更简单、更好的方法来做这些事情。

为什么 [ |c[0].WHAT ~~ Rat, with c[0] == 3/2] 不起作用?

我将首先简化,然后结束您的代码正在做什么:

say    3/2        ~~ Rat;  # True
say   (3/2)       ~~ Rat;  # True
say   (3/2).WHAT  ~~ Rat;  # True
say |((3/2).WHAT  ~~ Rat); # True
say (|(3/2).WHAT) ~~ Rat;  # False
say  |(3/2).WHAT  ~~ Rat;  # False
Run Code Online (Sandbox Code Playgroud)

最后一种情况是因为|具有比更高的优先级~~

有没有比字符串化和测试 Type 的字符串等价物更好的方法?

天啊是的。

使用类型,卢克。

(在您的用例中,请使用签名。)

内省

与在例程主体中手动内省传入数据的代码相比,适当使用签名通常会:

  • 更好地阅读;

  • 生成更好的底层代码;

  • 编译阶段进行部分或全部评估。

如果一种语言及其编译器通过提供特定功能(例如签名)来解决用例,那么使用该功能而不是自省通常会带来上述三个好处。

语言/编译器可以分为四类,即:

  1. 不要做或允许任何反省;

  2. 允许编译器自省,但不允许开发人员

  3. 允许编译器和开发人员进行自省,但旨在使其成为最后的手段,至少对于开发人员而言;

  4. 启用并鼓励开发人员进行自省。

Raku(do) 属于第三类。在此 SO 的上下文中,签名是主要功能,几乎消除了开发人员手动内省的任何需要。


jjm*_*elo 5

您可以简单地智能匹配到一个类型:

raku -e "sub a( *@c ) { say @c[0] ~~ Rat };a(3/2);a(2)" 
True
False
Run Code Online (Sandbox Code Playgroud)

此外,我在这里使用的是一个slurpy而不是捕获,这是另一种选择。无论如何,使用单个参数,您可能最好使用类型捕获

raku -e "sub a( ::T $ ) { say ::T ~~ Rat };a(3/2);a(2)" 
True
False
Run Code Online (Sandbox Code Playgroud)