每次我下载Rakudo Perl 6的新副本时,我都运行以下表达式,只是为了了解它当前的性能:
say [+] 1 .. 100000;
Run Code Online (Sandbox Code Playgroud)
并且速度一直在增加,但每次计算都有明显的延迟(几秒).作为比较,Perl 5(或其他解释语言)中的类似内容几乎立即返回:
use List::Util 'sum';
print sum(1 .. 100000), "\n";
Run Code Online (Sandbox Code Playgroud)
或者在Ruby中(也几乎是即时的):
(1 .. 100000).inject(0) {|sum,x| sum+x}
Run Code Online (Sandbox Code Playgroud)
将表达式重写为Perl6的loop速度大约是缩小范围的两倍,但对于简单的计算,它仍然是一个非常明显的延迟(超过一秒):
my $sum;
loop (my $x = 1; $x <= 100000; $x++) {$sum += $x}
Run Code Online (Sandbox Code Playgroud)
所以我的问题是,Perl6实现的哪些方面导致了这些性能问题?并且这应该随着时间的推移而改善,还是这个开销是Perl6使用的"一切都是对象"模型的不幸副作用?
最后,loop构造比[+]减速算子更快吗?我认为循环将导致更多的总操作而不是减少.
编辑:
我会接受这两个mortiz年代和hobbs'如果我能的回答.一切都是作为一个方法调用处理更直接地回答为什么[+]慢,所以一个人得到它.
你如何完全删除Perl中的包?这不仅意味着包变量,还意味着Perl更新以处理继承更改和其他事物的任何魔术表.
这个简单的测试:
use warnings; use strict;
use Test::LeakTrace;
use Symbol 'delete_package';
leaktrace {
package test;
our $x = 1;
package main;
delete_package 'test';
};
Run Code Online (Sandbox Code Playgroud)
得到以下输出:
leaked ARRAY(0x81c930) from /lib/perl5/5.10.1/Symbol.pm line 166.
leaked HASH(0x827760) from /lib/perl5/5.10.1/Symbol.pm line 166.
leaked SCALAR(0x821920) from /lib/perl5/5.10.1/Symbol.pm line 166.
Run Code Online (Sandbox Code Playgroud)
使用该-verbose标志来leaktrace显示我可以根据请求发布的数据屏幕.
如果将行our @ISA = 'main';添加到test包中,情况会变得更糟:
leaked ARRAY(0x81cd10) from so.pl line 32.
leaked SCALAR(0x81c930) from so.pl line 32.
leaked ARRAY(0x8219d0) from so.pl line 32.
leaked HASH(0x8219c0) from so.pl line 32. …Run Code Online (Sandbox Code Playgroud) 是否有任何类似于键盘的服务允许您在旧版本的perl上测试Perl构造?
理想情况下,您可以在其中输入表达式的系统,它将告诉您它将使用的最旧版本的perl.
当然可以使用CPANTS,但这似乎是滥用服务(如果只是为了使BackPan更大).可能需要几天/几周才能在旧版本上获得不错的测试覆盖率.
Perl没有$_使用以下语法自动进行本地化的设计(或技术)原因是什么:
while (<HANDLE>) {...}
Run Code Online (Sandbox Code Playgroud)
哪个被重写为:
while (defined( $_ = <HANDLE> )) {...}
Run Code Online (Sandbox Code Playgroud)
所有隐式写入其它结构的$_以集中方式做到这一点(for/foreach,map,grep),但是while,必须明确定位变量:
local $_;
while (<HANDLE>) {...}
Run Code Online (Sandbox Code Playgroud)
我的猜测是它与在命令行开关的"Super-AWK"模式下使用Perl有关,但这可能是错误的.
因此,如果有人知道(或者更好地参与语言设计讨论),您能否与我们分享这种行为背后的原因?更具体地说,为什么允许值$_在循环之外保持被认为是重要的,尽管它可能导致的错误(我倾向于在SO和其他Perl代码中看到所有这些)?
如果从上面不清楚,$_必须进行本地化的原因while如下例所示:
sub read_handle {
while (<HANDLE>) { ... }
}
for (1 .. 10) {
print "$_: \n"; # works, prints a number from 1 .. 10
read_handle;
print "done with $_\n"; # does not work, prints the last line read from …Run Code Online (Sandbox Code Playgroud) 我一直在研究在Perl 6中构造惰性列表的各种方法,我想收集描述Fibonacci序列的所有简洁方法.
我将从马萨克的期刊中的三个开始:
my @fibs := (0, 1, -> $a, $b { $a + $b } ... *);
my @fibs := (0, 1, { $^a + $^b } ... *);
my @fibs := (0, 1, *+* ... *);
Run Code Online (Sandbox Code Playgroud)
我认为这样的东西也会起作用,但我认为我的语法有误:
my @fibs := (0, 1, (@fibs Z+ @fibs[1..*]));
Run Code Online (Sandbox Code Playgroud)
有什么东西急切(切片?)并导致Rakudo进入无限循环.它是Haskell定义的翻译:
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
Run Code Online (Sandbox Code Playgroud)
更新:
看起来像zipWith示例的问题是@fibs[1..*]切片.if tail定义为sub tail (@x) {my $i = 1; {@x[$i++]}...*}然后它正常工作.我很想知道为什么切片对任何熟悉Rakudo内部的人来说都不是懒惰的.
另一个不错的是:
my …Run Code Online (Sandbox Code Playgroud) 从Perl 5.10开始,现在可以在语义上或在构造中$_明确地对上下文变量进行范围限定.my $_;given / when
有没有人发现词汇的好用$_?它是否使任何构造更简单/更安全/更快?
如果情况变得更复杂呢?词法是否在$_您的代码中引入了任何错误?(因为写入的控制结构$_将使用词法版本,如果它在范围内,如果它包含任何子例程调用(由于动态范围的丢失),这可以改变代码的行为)
最后,我想构建一个清单,明确何时$_用作词汇,全局,或者根本不重要.
注意:由于perl5-5.24这些实验性特征不再是perl的一部分.
我正在研究一个小型DSL,它使用nomethod回退进行重载来捕获重载值上使用的运算符.这类似于文档中描述的符号计算器的功能overload.
这适用于标准比较运算符,但请考虑以下事项:
my $ret = $overloaded =~ /regex/;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,nomethod调用stringify $overloaded,之后失去重载.我想要返回一个绑定变量,这至少会让我随身携带原始的重载对象,但在执行正则表达式时仍会丢失.
所以,最终的问题是,如果有什么办法可以延长overload的一个象征性的计算器的主意,包括正则表达式结合运营商=~和!~,使上面的代码示例将调用nomethod与($overloaded, qr/regex/, 0, '=~')或类似的东西?
我还简要介绍了重载smartmatch运算符,~~但似乎也没有做到这一点(总是默认为正则表达式匹配而不是重载).
编辑:我调查了~~更多,并发现my $ret = $overloaded ~~ q/regex/由于智能匹配规则的作用.关闭,但不是一个理想的解决方案,我希望它在5.10之前工作,所以我欢迎其他答案.
Perl数组是一种抽象数据类型.Perl数组的内部机制是什么?它是用动态数组还是链表实现的?由于数组元素具有随机访问权限,因此我假设一个动态的指针数组,或者对标量的引用是有意义的.但是,对于数组头部的移位和非移位操作,数组是否必须通过这些操作移动其所有元素?听起来对我来说效率低下.任何想法?
Perl中的常见做法当然是结束模块,1;以便可以检查对require的调用是否成功.有没有理由说返回值不是另一个真正的价值?在我的测试中,它不会导致任何问题,但我想知道是否有人遇到任何问题(例如一些其他模块或编译指示或任何期望值实际上1而不仅仅是真实的东西).
编辑:通过流行的观点,因为它只会工作一次(好的提示),代码示例消失了.似乎共识是它可以安全地返回任何真值,但从不依赖于调用代码中的那个值,因为它require会1在第一次加载后返回
没有特别的原因,我正在使用glob原型(*),看看当参数是一个已定义的子程序时它会做什么.
给出以下代码:
sub test (*) {print "[@_]\n"}
sub blah ($) {"blah got @_"}
Run Code Online (Sandbox Code Playgroud)
如果你写,test blah;你会得到语法错误Not enough arguments for main::blah...
如果你编写test blah 1;程序编译并打印[blah]
如果你编写test blah die;程序编译,打印[blah]并且不会死.
如果你编写test blah(1);程序编译并打印[blah got 1]
如果你编写test blah(die);程序编译然后死亡.
最后两个例子显然是"如果它看起来像一个子程序调用它是一个子程序调用"规则的应用.
但是,没有括号的例子对我来说似乎是个错误.因为似乎正在发生的事情是,尽管处于glob上下文中,解析器仍然将其blah视为需要参数的原型函数.但是当编译完成后,参数将blah被完全抛弃,而字符串'blah'则被传递给test.
以下是test blah die;构造运行的示例B::Deparse:
$ perl -MO=Deparse,-p -e 'sub test (*) {print "[@_]\n"} sub blah ($) {"blah got @_"} …Run Code Online (Sandbox Code Playgroud) perl ×10
perl6 ×2
raku ×2
fibonacci ×1
global ×1
lexical ×1
local ×1
memory-leaks ×1
module ×1
overloading ×1
package ×1
performance ×1
perl5.10 ×1
prototype ×1
rakudo ×1
regex ×1
syntax ×1
testing ×1
version ×1
while-loop ×1