什么语法,如果有的话,能够引用内置的像shift?
$shift_ref = $your_magic_syntax_here;
Run Code Online (Sandbox Code Playgroud)
您可以使用与用户定义的子相同的方式:
sub test { ... }
$test_ref = \&test;
Run Code Online (Sandbox Code Playgroud)
我尝试了以下,但都不起作用:
\&shift
\&CORE::shift
\&{'shift'}
\&{'CORE::shift'}
Run Code Online (Sandbox Code Playgroud)
如果需要,你的答案可以包括XS,但我不愿意.
澄清:我正在寻找一种通用解决方案,可以从任何内置程序获得功能齐全的代码参考.然后可以将此coderef传递给任何更高阶的函数,就像对用户定义的子的引用一样.到目前为止似乎是共识,这是不可能的,任何人都不同意?
在我的一个模块中,我必须处理无限的概念.到目前为止,我一直在使用9**9**9正无穷大,这似乎运作良好,速度快,似乎是perl的内部用作无限.
但是,如果我的模块的用户决定使用其中一个大数字模块(例如use bigint;),然后他们使用inf或Math::BigInt->binf()表示无穷大,事情会有点冒险.
在某些地方它似乎工作正常,但在其他地方,比较应该是真的或应该是错误的最终错误的方式导致难以追踪错误.
我想支持无限的其他各种概念,它们可以使用普通的perl数和任意精度数.
但我也对性能表示担忧,因为我对无穷大的一些比较发生在紧密的内环中.显然,inffrom Math::BigInt会慢于9**9**9(由于在每次访问时调用绑定或重载方法).过去有没有人处理过这个问题?如果是这样,你的解决方案是什么?
我已经考虑过将自己的常量用于无穷大,定义如下:
use constant INF => if_any_bignum_modules_loaded()
? Math::BigInt->binf
: 9**9**9;
Run Code Online (Sandbox Code Playgroud)
然后向我的模块添加警告,首先应该加载任何bignum模块.这听起来合情合理吗?是否有可靠的实施if_any_bignum...,或者我应该自己推出?
在Perl 5和Perl 6之间差异的总结中,注意到该wantarray功能已经消失:
wantarray()走了
wantarray走了.在Perl 6中,上下文向外流动,这意味着例程不知道它在哪个上下文中.
相反,你应该返回在每个上下文中做正确事情的对象.
有人可以举例说明如何创建这样的对象吗?
有没有人知道什么解析或优先级决定导致警告'使用'shift"没有括号是不明确的'为代码发出,如:
shift . 'some string';
# and not
(shift) . 'some string'; # or
shift() . 'some string';
Run Code Online (Sandbox Code Playgroud)
这是否有意使某些句法结构更容易?或者它只是perl解析器工作方式的工件?
注意:这是关于语言设计的讨论,而不是建议的地方
"@{[shift]}some string"
Run Code Online (Sandbox Code Playgroud) 我最近尝试在我的手机(诺基亚n900)上升级一些Perl模块,并安装最新版本的Module::Build一小时.
大多数情况下(70%)似乎花费在解析和索引存储库信息上.
似乎有一些选项,例如每次都不重建索引缓存,或者使用CPAN :: SQLite.
我想继续在设备上使用CPAN,而不是手动安装模块.所以我想知道人们在类似的有限资源设备上取得了哪些成功(缓慢的CPU,有限的RAM,慢速磁盘(闪存))?
假设我有一个名为的包My::Pkg,并且该包有一个->new(...)类方法来实例化新对象:
package My::Pkg;
sub new {bless {@_[1..$#_]} => $_[0]}
Run Code Online (Sandbox Code Playgroud)
定义以下子例程有什么危害:
sub My::Pkg {@_ ? My::Pkg::new('My::Pkg', @_) : 'My::Pkg'}
Run Code Online (Sandbox Code Playgroud)
所以有人可以写:
my $obj = My::Pkg one => 1, two => 2;
Run Code Online (Sandbox Code Playgroud)
而不是:
my $obj = My::Pkg->new(one => 1, two => 2); # which still works, but is longer
Run Code Online (Sandbox Code Playgroud)
我喜欢package-named-constructor-subroutine方法的简洁性,但我很想知道这个技术是否有任何隐藏的问题,我没有想到.
更新:
继承正常工作,如下例所示:
{package a; sub new {say "a::new [@_] ", $_[0]->init}}
{package b; our @ISA = 'a'; sub init {"(b::init [@_])"}}
{package a::b; our @ISA = 'b';}
sub a::b …Run Code Online (Sandbox Code Playgroud) 我有许多高阶实用程序函数,它们接受代码引用并将该代码应用于某些数据.其中一些函数需要在执行子例程期间本地化变量.开始时,我正在使用caller以与此示例reduce函数中所示类似的方式确定要本地化的包:
sub reduce (&@) {
my $code = shift;
my $caller = caller;
my ($ca, $cb) = do {
no strict 'refs';
map \*{$caller.'::'.$_} => qw(a b)
};
local (*a, *b) = local (*$ca, *$cb);
$a = shift;
while (@_) {
$b = shift;
$a = $code->()
}
$a
}
Run Code Online (Sandbox Code Playgroud)
最初这种技术运行良好,但是当我尝试围绕高阶函数编写包装函数时,找出正确的调用者变得复杂.
sub reduce_ref (&$) {&reduce($_[0], @{$_[1]})}
Run Code Online (Sandbox Code Playgroud)
现在为了reduce工作,我需要这样的东西:
my ($ca, $cb) = do {
my $caller = 0;
$caller++ while caller($caller) =~ /^This::Package/;
no strict …Run Code Online (Sandbox Code Playgroud) 在下面的匿名子例程声明中,Perl似乎将其解析为间接方法调用,而不是作为子例程:
use 5.010;
use strict;
use warnings;
sub proxy {
my $new = shift;
say "creating proxy: $new";
sub :lvalue {
say "running proxy: $new";
tie my $ret, 'Some::Package', shift, $new;
$ret
}
}
say "before";
my $p1 = proxy '_value';
say "p1 declared: $p1";
my $p2 = proxy 'value';
say "p2 declared: $p2";
Run Code Online (Sandbox Code Playgroud)
打印:
before creating proxy: _value running proxy: _value Can't locate object method "TIESCALAR" via package "Some::Package" ...
如果a return或者my $sub =之前添加sub :lvalue …
在我的测试中,我注意到迭代绑定数组的速度最好是使用内部存取方法(FETCH和FETCHSIZE)的一半.以下基准显示了该问题:
{package Array;
sub new {
my $class = shift;
tie my @array, $class, [@_];
\@array
}
sub TIEARRAY {
my ($class, $self) = @_;
bless $self => $class;
}
sub FETCH {$_[0][$_[1]]}
sub FETCHSIZE {scalar @{$_[0]}}
}
use List::Util 'sum';
use Benchmark 'cmpthese';
for my $mag (map 10**$_ => 1 .. 5) {
my $array = Array->new(1 .. $mag);
my $tied = tied(@$array);
my $sum = sum @$array;
print "$mag: \n";
cmpthese -2 => { …Run Code Online (Sandbox Code Playgroud) 类似于AUTOLOAD可以根据需要定义子例程的方式,我想知道是否有办法绑定一个包的存储,以便我可以拦截对该包中变量的访问.
我尝试了以下想法的各种排列,但似乎都没有效果:
{package Tie::Stash;
use Tie::Hash;
BEGIN {our @ISA = 'Tie::StdHash'}
sub FETCH {
print "calling fetch\n";
}
}
{package Target}
BEGIN {tie %Target::, 'Tie::Stash'}
say $Target::x;
Run Code Online (Sandbox Code Playgroud)
这Bad symbol for scalar ...在最后一行死亡,没有打印"calling fetch".如果say $Target::x;删除该行,程序将运行并正确退出.
我的猜测是失败与stashes有关,但与散列不一样,所以标准的tie机制不能正常工作(或者它可能就是stash lookup永远不会调用tie魔法).
有谁知道这是否可能?Pure Perl是最好的,但XS解决方案还可以.
perl ×10
syntax ×4
biginteger ×1
bignum ×1
constructor ×1
cpan ×1
infinity ×1
module ×1
performance ×1
perl-stash ×1
perl5 ×1
perl6 ×1
raku ×1
tie ×1
warnings ×1