- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
转发注释: 为了便于讨论,请暂时忽略这样一个事实:通过 Class::Accessor 可以实现相同的目的。 ,或者甚至简单地使用 Moose (在考虑代码可读性和可维护性时可能会得到更好的结果)。
关于面向对象的 Perl,《Programming Perl》一书讨论了使用闭包生成访问器方法的能力。例如,这是一段有效的代码:
#!perl
use v5.12;
use warnings;
# at run-time
package Person1;
my @attributes = qw/name age address/;
for my $att ( @attributes )
{
my $accessor = __PACKAGE__ . "::$att";
no strict 'refs'; # allow symbolic refs to typeglob
*$accessor = sub {
my $self = shift;
$self->{$att} = shift if @_;
return $self->{$att};
};
}
sub new { bless {}, shift }
package main;
use Data::Dumper;
my $dude = Person1->new;
$dude->name('Lebowski');
say Dumper($dude);
在上面的示例中,如果我没有记错的话,该类是在运行时组成的,其访问器是在实例化该类的同时创建的。这意味着对象创建的速度会受到影响。
现在考虑以下替代方案:
#!perl
use v5.12;
use warnings;
package Person2;
BEGIN
{
for my $att (qw/name age address/)
{
my $accessor = __PACKAGE__ . "::$att";
no strict 'refs'; # allow symbolic refs to typeglob
*$accessor = sub {
my $self = shift;
$self->{$att} = shift if @_;
return $self->{$att};
};
}
}
sub new { bless {}, shift }
package main;
use Data::Dumper;
my $dude = Person2->new;
$dude->name('Lebowski');
say Dumper($dude);
在此版本中,组合是在 BEGIN
block 内(即在编译时)进行的,我相信通过在生命周期中尽快处理此任务对于程序,我在运行时实例化对象期间节省了时间。
一个简单的基准
,
# benchmark it!
package main;
use Benchmark qw/cmpthese/;
cmpthese(-2, {
accessors_new => sub { Person1->new },
accessors_begin => sub { Person2->new },
});
这些结果似乎支持了我的理论:
Rate accessors_begin accessors_new
accessors_begin 853234/s -- -9%
accessors_new 937924/s 10% --
假设到目前为止我的推理是正确的,
BEGIN
block 作为执行此类类操作的有效方法是个好主意吗?最佳答案
当我运行你的基准测试时,我得到了相当多的抖动,这可能是你的差异的原因。对于任何 10% 或更少的差异,请运行多次以确保确定。
Rate accessors_begin accessors_new
accessors_begin 1865476/s -- -4%
accessors_new 1943339/s 4% --
Rate accessors_begin accessors_new
accessors_begin 1978799/s -- -1%
accessors_new 2001062/s 1% --
Rate accessors_new accessors_begin
accessors_new 1943339/s -- -2%
accessors_begin 1988089/s 2% --
Rate accessors_begin accessors_new
accessors_begin 1796509/s -- -8%
accessors_new 1949296/s 9% --
Rate accessors_begin accessors_new
accessors_begin 1916122/s -- -3%
accessors_new 1969595/s 3% --
但实际上,您所进行的基准测试只是sub new { bless {}, shift }
。对同一事物进行自身基准测试会强调颤振。当代码加载时,生成访问器的工作就已经完成,并且永远不会进入其中,无论是否是 BEGIN block 。
Perl 没有单一的编译时和运行时。相反,use
d、require
d 或 eval
ed 的每件事都会经历其自己的编译和运行时步骤。 use Some::Class
导致 Some/Class.pm
经历编译和运行时执行 BEGIN
,编译子例程,然后执行任何其他代码。无论代码位于模块内的 BEGIN block 内部还是外部,与该模块外部的代码几乎没有什么区别。
关于perl - 使用闭包修改 Perl BEGIN block 中的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9601545/
我想处理 vector 中的元素一段时间。为了优化这一点,我不想在处理项目时删除它,而是在最后删除所有已处理的项目。 vector::iterator it; for(it = items.begin
我对 perl 中的 const 声明有疑问,并且无法弄清楚差异,请指出有什么不同。 下面是代码: BEGIN { *SIZE = sub() { 2 }; } *ITEM = sub() {
在右值上调用std::vector 和std::begin() 的成员函数.begin() 会导致不同的输出, 如以下测试所示: vector a{ 1, 2, 3 }; vector::iterat
我正在尝试创建自己的 vector 类。目前,我正在为我的 vector 类 Vec 添加一个删除函数。当我将 variable.begin() 传递到 erase 函数参数时,我的代码会报错,但在我
在 c++ 中迭代 vector 时,我注意到标准库中有一个 begin() 函数,还有一个 begin() 作为成员函数vector 类。如果有的话,两者之间有什么区别,应该使用哪个而不是另一个?
为什么标准将 end() 定义为末尾,而不是实际末尾? 最佳答案 最好的论据是Dijkstra himself 提出的论据。 : 您希望范围的大小是一个简单的差异end - begin; 当序列退化为
我正在尝试遍历大量记录并处理它们中的每一个。即使在处理过程中发生错误,游标也应该继续循环遍历记录,但在批处理结束时,我希望看到所有产生错误的记录的错误消息。 我有以下代码: 选择.... OP
这个问题在这里已经有了答案: error: no matching function for call to 'begin(int*&)' c++ (3 个答案) 关闭 6 年前。 我想获取数组的长
如果我有 std::vector(它是一个 std::vector 并且永远是一个 std::vector)。 使用 std::begin() 代替 std::vector::begin()(或相反)
这个问题在这里已经有了答案: Why use non-member begin and end functions in C++11? (7 个答案) 关闭 4 年前。 在这个问题(https://
我一直在尝试在网络上查找有关这些陈述之间差异的信息,在我看来它们是相同的,但我找不到对此的确认或两者之间的任何类型的比较。 这样做有什么区别: BEGIN -- Some update, in
我正在使用 Tiled Map 学习 LibGDX。我遇到了以下两种渲染方法。第一个是我通常使用的简单的。 但是,我不明白为什么我们需要第二个。我可以使用 batch.begin();在方法 2 中也
是否可以在 SpriteBatch begin 和 end 调用之间使用 ShapeRenderer 绘制形状。 我已经尝试过但没有结果,只绘制了 SpriteBatch 纹理,场景中没有任何形状。示
嗨,我正在编写一个程序,该程序从 .pem 文件导入私钥并创建一个私钥对象以供稍后使用。我遇到的问题是一些 pem 文件头以 开头 -----BEGIN PRIVATE KEY----- 而其他人则以
关闭。这个问题是off-topic .它目前不接受答案。 想改善这个问题吗? Update the question所以它是 on-topic对于堆栈溢出。 9年前关闭。 Improve this q
观看 Stephan T. Lavavej:核心 C++ #1,并注意到他使用的是 begin(collection) 而不是 collection.begin()。 有什么优势? 最佳答案 我想到的
Python脚本 ''' a ''' from __future__ import print_function 运行良好(即什么都不做),但是 ''' a ''' ''' b ''' from __
如何在两种风格的公钥格式之间进行转换, 一种格式是: -----BEGIN PUBLIC KEY----- ... -----END PUBLIC KEY----- 另一种格式是: -----BEGI
我是 STL c++ 的新手。我从书中复制了这个函数: string ConverToLowerCase(string s) { transform(s.begin(), s.end(),
给定代码: #include #include #include #include using namespace std; int main() { string s("ABCDE
我是一名优秀的程序员,十分优秀!