bri*_*foy 9 set perl6 moarvm raku
在呐喊下奔跑(2016.10)
考虑构造一个集合并测试成员资格的代码:
my $num_set = set( < 1 2 3 4 > );
say "set: ", $num_set.perl;
say "4 is in set: ", 4 ? $num_set;
say "IntStr 4 is in set: ", IntStr.new(4, "Four") ? $num_set;
say "IntStr(4,...) is 4: ", IntStr.new(4, "Four") == 4;
say "5 is in set: ", 5 ? $num_set;
Run Code Online (Sandbox Code Playgroud)
直接4不在集合中,但IntStr版本是:
set: set(IntStr.new(4, "4"),IntStr.new(1, "1"),IntStr.new(2, "2"),IntStr.new(3, "3"))
4 is in set: False
IntStr 4 is in set: True
IntStr(4,...) is 4: True
5 is in set: False
Run Code Online (Sandbox Code Playgroud)
我想大多数人都不会指望这一点,但是?文档并没有说明这可能如何起作用.如果我不使用引用词(即set( 1, 2, 3, 4)),我没有这个问题.
你在中间转了个弯.重要的部分是nqp::existskey所谓的:k.WHICH.这个方法适用于值类型,即不可变类型,其中值 - 而不是标识 - 定义两个事物是否应该是同一个事物(即使创建两次).它返回一个对象值的字符串表示,该值对于两个应该相等的事物是相等的.因为<1>.WHICH你得到IntStr|1并为1.WHICH你得到了Int|1.
我认为这是一个错误,但不是在设定的东西中。其他答案对于区分什么重要、什么不重要非常有帮助。
我使用了尖括号形式的引用词。引用词形式应该等同于引用版本(即, True under eqv)。这是文档示例:
<a b c> eqv ('a', 'b', 'c')
Run Code Online (Sandbox Code Playgroud)
但是,当我用一个全是数字的单词尝试这个时,这就被破坏了:
$ perl6
> < a b 137 > eqv ( 'a', 'b', '137' )
False
Run Code Online (Sandbox Code Playgroud)
但是,其他形式也有效:
> qw/ a b 137 / eqv ( 'a', 'b', '137' )
True
> Q:w/ a b 137 / eqv ( 'a', 'b', '137' )
True
Run Code Online (Sandbox Code Playgroud)
尖括号单词引用使用IntStr:
> my @n = < a b 137 >
[a b 137]
> @n.perl
["a", "b", IntStr.new(137, "137")]
Run Code Online (Sandbox Code Playgroud)
如果没有引用单词,数字单词将显示为 [Str]:
> ( 'a', 'b', '137' ).perl
("a", "b", "137")
> ( 'a', 'b', '137' )[*-1].perl
"137"
> ( 'a', 'b', '137' )[*-1].WHAT
(Str)
> my @n = ( 'a', 'b', '137' );
[a b 137]
> @n[*-1].WHAT
(Str)
Run Code Online (Sandbox Code Playgroud)
当有两条代码路径来获得最终结果而不是很早就收敛到一条路径的共享代码时,您通常会看到此类错误。如果我想追踪这个问题,这就是我会寻找的(但是,我需要写这本书!)
不过,这确实强调了您必须非常小心地对待集合。即使这个错误被修复,还有其他无错误的方法eqv可能会失败。我仍然会失败,因为Int 的4不是Str的“4” 。我认为这种对数据类型的关注在 DWIMery 中是不恰当的。这当然是我必须在课堂上非常仔细地解释的事情,但仍然看着每个人都搞砸了。
就其价值而言,我认为 的结果gist往往会因过于简单化而产生误导,有时 的结果perl不够丰富(例如隐藏Str,这迫使我这样做.WHAT)。我使用它们的次数越多,我发现它们的用处就越小。
但是,在开始之前就知道我搞砸了,这会让我免于陷入那些最终毫无意义的代码探索之中!