简而言之:我喜欢take 0。有一个解决方法(参见take1),但我认为这不值得。我认为使用纯my
不会效率低下(参见take2)。我认为在编译时应该拒绝使用带有正则表达式/方法的state
(参见take3和5),或者保留原样(参见take4)。除非你是一个编程天才,愿意说服jnthn让Rakudo大幅增加对continuations的曝光(参见take5)。
这到底是为什么?(take 1)
如果您像这样编写,则不会出现“这”:
sub test-string( $string )
{
state &opening-brace = token { \( }
state &closing-brace = token { \) }
state &balanced-braces = token {
( <&opening-brace>+ ) <&closing-brace> ** { $0.chars }
}
so $string ~~ /^ <&balanced-braces> $/;
}
(正则表达式调用中需要使用&
这个符号,有点让我感到意外。1)
这到底是为什么?(第二篇)
发生了什么事情?
我认为第一个版本在每次调用函数时都必须设置标记,因此效率相当低。
你所说的“认为”、“相当低效”、“设置标记”是什么意思?我期望正则表达式代码只会被编译一次(如果每次都编译,我会感到震惊),但还没有进行性能测试以验证。
这引发了一系列问题:
你的担忧纯粹是每次调用test-string
函数时重新创建3个lexpad条目(例如&opening-parens
等;更普遍地说,正则表达式的数量)所花费的时间吗?
你是否真正对运行原始代码进行了性能分析,并发现存在显著问题?
你是否真的测量过这一点,并发现它是你实际项目中“关键的三分之一”?
为什么会发生这种情况?(第三次尝试)
state
声明符对于sub
做了一个合理的处理——它会产生编译时错误:
state sub foo {}
state my sub foo {}
但是使用一种方法(正则表达式实际上就是这样)进行编译,虽然可以通过,但却没有任何有用的作用:
state method foo {}
state regex bar {.}
我查看了Rakudo的GH问题队列,未能找到讨论上述代码最后两行(与您的token
案例基本相同)的问题。也许人们没有注意到这一点,或者至少认为提交错误不会有帮助?
为什么会发生这种情况?(第4次尝试)
因此,您可以发布一个SO文档,说明state regex
应该在编译时被拒绝或做一些有用的事情。@Scimon++会记录另一种观点。还有我。
为什么会发生这种情况?(第5次尝试)
<Your Compiler Code Goes Here>
因为 Raku 是我们的大型多人在线角色扮演游戏(MMORPG),如果您希望在例程声明时使用state
声明符号有用的功能(假设它应该像当前与sub
一起使用时产生编译时错误,或在Raku构建的"scoped continuations"约束下执行一些花哨的连续操作),那么这项工作可能只是一个“smop”(即简单的方法)就可以实现,因为Rakudo编译器大部分是用Raku语言编写的。某个人故意将sub
上的state
设置为编译时错误,而连续概念将是一个真正庞大的项目,所以我认为,如果有任何适当的措施,未来几年内在方法或规则上使用state
也应该成为编译时错误。
或者,更合适的是,现在已经有了SO,有文档化的替代方案(语法)和解决方法(take 1),现在是时候转向下一个层次了...
脚注
1 请参见我对Difference in ... regex scope问题的回答。使用state
声明的正则表达式的行为似乎不遵循我在那个回答中引用的设计推测的直观阅读。并且,至少从那个答案中以下部分的叙述也是错误的...
"<bar>
如上所述。它优先解析为一个早期绑定的词法(my
/our
)程序/规则,名称为&bar
。
...因为在本答案的第一次尝试代码中,正则表达式调用必须以&
为前缀才能工作。也许这只是偶然的,它们根本不起作用。
sub foo { state $foo++; state $bar--; $foo, $bar }; foo; say foo;
显示(2 -2)
。只是“state”不能在程序声明中工作(正如Holli的问题和我在回答中探讨的那样)。这与想要为程序调用使用“state”并不相同。(尽管如此,我认为语法可能是最佳选择。我猜它会比我的回答中的任何方法都更好且执行效果更佳。) - raiphsay token {.}.^mro
。你不需要更清楚了。"[a sub won't] keep a state from one call to the next." 你难道看不出你措辞的问题吗?你如何解释我之前评论中的结果(2 -2)
而非(1 -1)
呢? "There's no way". Raku 中的一个更激进的特点是它是建立在作用域 continuation 之上的,因此甚至有一种方式来保留调用帧。这就是动态交叉调用gather
/take
的工作原理。 - raiphstate
来声明例程类似于海市蜃楼,因为例程声明无论如何都会声明一个常量。这就是为什么我在我的答案中写下了take 2。我想引导Holli通过精确的实际用例证明他们需要解决的问题,或者意识到事情已经相当优化。我完全希望他们得出后者的结论,但我将take 2放在take 1之后,因为我不想从线索开始,而且我可能误解了他们的说法或事物的运作方式。 - raiph