2011-11-16 46 views
1

我对perl有一个想法,我试图找出实现它的最佳方法。perl - 通用运算符过载

这个想法是让每个操作符的新版本将未定义的值视为该操作的标识。例如:

$a = undef + 5;  # undef treated as 0, so $a = 5 
$a = undef . "foo"; # undef treated as '', so $a = foo 
$a = undef && 1; # undef treated as false, $a = true 

等等。

理想情况下,这将在语言中作为编译指示或其他。

use operators::awesome; 

不过,我会满意,如果我能实现这个特殊的逻辑我自己,然后调用它需要的地方:

use My::Operators; 

的问题是,如果我说“超负荷使用”我的里面: :操作符只会影响到My :: Operators中保存的对象。

所以问题是:有没有一种方法(用“使用overoad”或其他方式)做一个“通用运算符超负荷” - 这将被称为所有操作,而不仅仅是有福的标量操作。

如果不是 - 谁认为这将是一个好主意!这将节省我这种代码的TON

if($object && $object{value} && $object{value} == 15) 

replace with 

if($object{value} == 15) ## the special "is-equal-to" operator 
+9

此编译指示已存在。它被称为“没有警告”; – mob

+1

我假设你打算说'$ object - > {value}'而不是'$ object {value}'。 – cjm

回答

3

所有这些操作已经工作的方式,你希望他们:

  • 在数字的情况下,undef0
  • 在字符串的情况下,undef是空字符串''
  • 在布尔值的情况下,undef0

如果你use warnings,那么perl会让你知道该值是未初始化的,但它仍然可以正常工作。

+1

简短,并重点。谢谢!我应该想到这一点。 –

4

正如暴徒说,你的编译指示已经存在。拼写为no warnings 'uninitialized';。 Perl已经将undef视为0或空字符串(取决于上下文)。这只是抑制了你通常得到的警告(假设你有警告打开,你应该)。

如果你想创建一个软件包,自动执行此操作,您可以:

package operators::awesome; 

use strict; 
use warnings; 

sub import { 
    warnings->unimport('uninitialized'); 
} 

现在use operators::awesome;将关闭约未初始化值的警告。

下面是一个发烧友版import是严格和警告曲折,但关闭的警告未初始化值:

sub import { 
    strict->import; 
    warnings->import; 
    warnings->unimport('uninitialized'); 
} 
+0

这与仅仅使用'no warnings'uninitialized''有什么不同? – TLP

+0

@TLP,它不是。我只是指出你可以编写一个相当于为你“没有初始化”警告的软件包。它也可以做其他事情,比如打开严格的警告和其他警告。它甚至可以导出函数,如果你想要的话,虽然这会更复杂。 – cjm

+0

因为'$ a = undef && 1;' – ikegami

6

这是可能。这将需要很多工作,但是你可以写一个“op检查器”,用自定义操作替代&&的操作,这就是你重新实现的&&

但这将是一个非常糟糕的主意。对于初学者来说,

if ($a && $b) { 
    ... 
} 

将停止等同于

if ($a) { 
    if ($b) { 
     ... 
    } 
} 

要把握自己的例子,

if ($object && $object{value} && $object{value} == 15) { 
    ... 
} 

有了您的要求的模型,它会被写入

if ($object{value}) { if ($object{value} == 15) { 
    ... 
}} 

您执行盟友希望与你所要求的完全相反。你实际上想要当前的行为。没有你的模块,你可以写:

if ($object{value} && $object{value} == 15) { 
    ... 
} 

no warnings 'uninitialized'; 
if ($object{value} == 15) { 
    ... 
} 

if (($object{value} // 0) == 15) { 
    ... 
} 
+0

你是对的,没有任何警告'未初始化'做了我所说的大部分。尽管如此,请注意提供关于“自定义op检查器”的更多细节?我不知道Perl如何让你在两个字面数之间钩住运算符。 –

+0

@Todd Freed,op检查器访问每一个操作,并可以替换他人。这是[autovivification](http://search.cpan.org/perldoc?autovivification)(模块)的工作原理。 – ikegami

+0

autovivification模块似乎完全在xs中实现。所以我猜你不能在纯perl中重载操作符? –