O=Deparse 是如何工作的,Perl 有和折叠常量数组吗?
Posted
技术标签:
【中文标题】O=Deparse 是如何工作的,Perl 有和折叠常量数组吗?【英文标题】:How does O=Deparse work, and does Perl have and fold constant arrays? 【发布时间】:2011-04-03 10:29:39 【问题描述】:我想知道,-MO=Deparse
是否向您展示了所有 Perl 优化,为什么不将其折叠到 Perl 5.10 中?
$ perl -MO=Deparse -e'[qw/foo bar baz/]->[0]'
['foo', 'bar', 'baz']->[0];
-e syntax OK
IRC 上的一些人认为 O=Deparse
可能没有显示全部,但它肯定显示了一些不断的折叠。
$ perl -MO=Deparse -e'use constant "foo" => "bar"; foo'
use constant ('foo', 'bar');
'???';
-e syntax OK
如果我显式编写常量 sub,结果相同。虽然可以预测,但同样有趣的是,constant.pm
中的文档让您创建了一个常量列表,而不是一个常量数组。我假设这不仅不像标量常量那样折叠,而且它需要在每次调用时创建一个新数组的开销。
$ perl -MO=Deparse -e'use constant foo => qw/foo bar baz/; (foo)[0]'
use constant ('foo', ('foo', 'bar', 'baz'));
(foo)[0];
-e syntax OK
我能得出的唯一结论是-MO=Deparse
显示了所有的折叠,而常量数组只是没有在 Perl 中优化?是这样吗?有技术原因吗?
【问题讨论】:
我仍然很困惑,为什么我会因此而被否决?有人给我留言。是不是因为这个问题太深奥了?您认为这将需要付出很多努力才能获得任何收益?我只是在问它是否可以完成,以及为什么它没有完成。 leading answer 似乎遇到了我问的同样的问题。 (1)假设由于技术原因无法完成(2)然后假设它根本没有完成,(3)然后推测它没有完成,因为它不够重要。 【参考方案1】:您不能创建常量数组,因为数组不是数据。 Perl 5 有五种类型的数据(可以存储在变量中的东西):
无值(未定义) 数字 字符串 参考文献 列表(由一种或多种上述类型组成)您可以将其中任何一个设为常数。 Perl 5 也有三个容器:
标量 数组 哈希标量可以保存前四种数据类型中的任何一种,数组和散列可以保存列表。重要的是不要混淆保存数据的东西和数据本身。
至于B::Deparse
,它在构建后会转储optree,所以它会显示所有常量折叠的结果。
我还没有考虑够多,但我没有看到任何明显的原因导致它不能折叠。
【讨论】:
你能解释一下-MO=Deparse -e'use strict; print ->[1]
和use strict; print ->[1]
。在某些时候,strict 知道您正在尝试获取第 N 个元素的无效引用(即
是一个哈希引用)。我知道我们常说严格运行的状态是编译时。 strict 如何知道这是什么类型的参考?你能解释一下这个方向吗?
@Evan Carroll 严格的编译指示没有注意到这一点,它只关心变量的声明 ("vars"
)、禁止符号引用 ("refs"
) 和禁止大多数裸字字符串 (@987654328 @)。 ->
运算符在运行时取消引用,这就是为什么我们在那之前不会收到错误的原因。如果我们让->
进行常量折叠,我们可能会在编译时捕获该特定错误。
经验法则一直是strict
不会减慢运行时间。这样做的事情是为warnings.pm
保留的。那么严格是在 BEGIN 期间在运行时通过操作树并抛出异常,还是严格断言 reftype 在运行时以速度成本有效? -- 或者,我还是没听懂。
strict
编译指示不能减慢运行时(除非你的运行时通过字符串 eval
包含新的编译时间)。它的所有影响都在编译时。我相信strict
在构建 optree 时运行,而不是之后。您还没有得到关于strict
的信息。这是一个 Perl 5 运行时错误,与 strict
或 warnings
无关。它类似于perl -e '$x=$y=0; $x/$y'
。
你是完全正确的,ekk perl -e'die; print ->[1]'
这是一个运行时断言,可以捕捉到这一点。【参考方案2】:
你不能在 Perl 中创建一个常量数组,内部没有任何东西可以指示一个常量数组或散列,甚至是一个标量。 “使用常量”利用了 Perl 的内联子程序的能力,其原型为 ()
和简单的代码。您可以做的最好的事情是设置readonly 标志,但可以在运行时将其关闭。
Perl 可以在编译时使用 readonly 标志作为提示来指示数组确实是只读的,然后使用常量索引内联任何访问。这样的启发式可能是安全的,因为只读标志不应该是用户可访问的,您可能不应该将其关闭。
【讨论】:
..如果你这样做了,你应该得到你所得到的:)以上是关于O=Deparse 是如何工作的,Perl 有和折叠常量数组吗?的主要内容,如果未能解决你的问题,请参考以下文章
将多个小标题导出到 XLSX -- 使用 deparse(substitute()) 时的 sheetName 问题
NumPy 多维数组迭代是如何工作的? (有和没有 nditer)
如何使用 Perl 删除 Excel 工作表中的整列并在新的 Excel 文件中写入更新的数据?