2010-05-24 39 views
27

我目前正在记录Perl 5的所有操作符(请参阅perlopref GitHub项目),并且我决定也包含Perl 5的伪操作符。对我而言,Perl中的伪运算符是任何看起来像运算符的东西,但实际上不止是一个运算符或其他一些语法。我已经证明这四个我熟悉不已:Perl 5中存在哪些伪操作符?

  • ()=的countof操作
  • =()=的goatse/countof操作
  • ~~标量上下文运算
  • }{爱斯基摩吻运营商

这些伪操作符还有其他什么名字,你知道我错过的伪操作吗?

=head1 Pseudo-operators 

There are idioms in Perl 5 that appear to be operators, but are really a 
combination of several operators or pieces of syntax. These pseudo-operators 
have the precedence of the constituent parts. 

=head2()= X 

=head3 Description 

This pseudo-operator is the list assignment operator (aka the countof 
operator). It is made up of two items C<()>, and C<=>. In scalar context 
it returns the number of items in the list X. In list context it returns an 
empty list. It is useful when you have something that returns a list and 
you want to know the number of items in that list and don't care about the 
list's contents. It is needed because the comma operator returns the last 
item in the sequence rather than the number of items in the sequence when it 
is placed in scalar context. 

It works because the assignment operator returns the number of items 
available to be assigned when its left hand side has list context. In the 
following example there are five values in the list being assigned to the 
list C<($x, $y, $z)>, so C<$count> is assigned C<5>. 

    my $count = my ($x, $y, $z) = qw/a b c d e/; 

The empty list (the C<()> part of the pseudo-operator) triggers this 
behavior. 

=head3 Example 

    sub f { return qw/a b c d e/ } 

    my $count =()= f();    #$count is now 5 

    my $string = "cat cat dog cat"; 

    my $cats =()= $string =~ /cat/g; #$cats is now 3 

    print scalar(()= f()), "\n"; #prints "5\n" 

=head3 See also 

L</X = Y> and L</X =()= Y> 

=head2 X =()= Y 

This pseudo-operator is often called the goatse operator for reasons better 
left unexamined; it is also called the list assignment or countof operator. 
It is made up of three items C<=>, C<()>, and C<=>. When X is a scalar 
variable, the number of items in the list Y is returned. If X is an array 
or a hash it it returns an empty list. It is useful when you have something 
that returns a list and you want to know the number of items in that list 
and don't care about the list's contents. It is needed because the comma 
operator returns the last item in the sequence rather than the number of 
items in the sequence when it is placed in scalar context. 

It works because the assignment operator returns the number of items 
available to be assigned when its left hand side has list context. In the 
following example there are five values in the list being assigned to the 
list C<($x, $y, $z)>, so C<$count> is assigned C<5>. 

    my $count = my ($x, $y, $z) = qw/a b c d e/; 

The empty list (the C<()> part of the pseudo-operator) triggers this 
behavior. 

=head3 Example 

    sub f { return qw/a b c d e/ } 

    my $count =()= f();    #$count is now 5 

    my $string = "cat cat dog cat"; 

    my $cats =()= $string =~ /cat/g; #$cats is now 3 

=head3 See also 

L</=> and L</()=> 

=head2 ~~X 

=head3 Description 

This pseudo-operator is named the scalar context operator. It is made up of 
two bitwise negation operators. It provides scalar context to the 
expression X. It works because the first bitwise negation operator provides 
scalar context to X and performs a bitwise negation of the result; since the 
result of two bitwise negations is the original item, the value of the 
original expression is preserved. 

With the addition of the Smart match operator, this pseudo-operator is even 
more confusing. The C<scalar> function is much easier to understand and you 
are encouraged to use it instead. 

=head3 Example 

    my @a = qw/a b c d/; 

    print [email protected], "\n"; #prints 4 

=head3 See also 

L</~X>, L</X ~~ Y>, and L<perlfunc/scalar> 

=head2 X }{ Y 

=head3 Description 

This pseudo-operator is called the Eskimo-kiss operator because it looks 
like two faces touching noses. It is made up of an closing brace and an 
opening brace. It is used when using C<perl> as a command-line program with 
the C<-n> or C<-p> options. It has the effect of running X inside of the 
loop created by C<-n> or C<-p> and running Y at the end of the program. It 
works because the closing brace closes the loop created by C<-n> or C<-p> 
and the opening brace creates a new bare block that is closed by the loop's 
original ending. You can see this behavior by using the L<B::Deparse> 
module. Here is the command C<perl -ne 'print $_;'> deparsed: 

    LINE: while (defined($_ = <ARGV>)) { 
     print $_; 
    } 

Notice how the original code was wrapped with the C<while> loop. Here is 
the deparsing of C<perl -ne '$count++ if /foo/; }{ print "$count\n"'>: 

    LINE: while (defined($_ = <ARGV>)) { 
     ++$count if /foo/; 
    } 
    { 
     print "$count\n"; 
    } 

Notice how the C<while> loop is closed by the closing brace we added and the 
opening brace starts a new bare block that is closed by the closing brace 
that was originally intended to close the C<while> loop. 

=head3 Example 

    # count unique lines in the file FOO 
    perl -nle '$seen{$_}++ }{ print "$_ => $seen{$_}" for keys %seen' FOO 

    # sum all of the lines until the user types control-d 
    perl -nle '$sum += $_ }{ print $sum' 

=head3 See also 

L<perlrun> and L<perlsyn> 

=cut 
+1

在一个侧面说明,恕我直言,爱斯基摩人的吻是欢闹的XD – 2010-05-24 14:58:15

+0

什么是'+ =',' - =','/ =','* =','** =电路运算符'|| =或// ='?他们是伪操作吗? – Zaid 2010-05-24 14:58:26

+0

@ Zaid不,那些确实是运营商。它们记录在perlop中的Assignment Operators(http://perldoc.perl.org/perlop.html#Assignment-Operators)下,并在我的文档中单独列出。 – 2010-05-24 15:01:52

回答

18

尼斯项目,这里有几个:

scalar x!! $value # conditional scalar include operator 
(list) x!! $value # conditional list include operator 
'string' x/pattern/ # conditional include if pattern 
"@{[ list ]}"  # interpolate list expression operator 
"${\scalar}"   # interpolate scalar expression operator 
!! $scalar   # scalar -> boolean operator 
+0     # cast to numeric operator 
.''     # cast to string operator 

{ ($value or next)->depends_on_value() } # early bail out operator 
# aka using next/last/redo with bare blocks to avoid duplicate variable lookups 
# might be a stretch to call this an operator though... 

sub{\@_}->(list) # list capture "operator", like [ list ] but with aliases 
+1

我喜欢'x !!'技巧,但是当我真的需要它时通常会忘记它,最后做一个'($ cond?$ foo:())'代替。 – friedo 2010-05-24 15:14:41

+0

废话,我忘了所有关于!布尔操作。我不知道+0还是。“真的很重要,但我想加入它们并没有什么坏处。插值技巧是一个明确的包含。我从来没有考虑过使用重复操作符,这些都是明确的补充。谢谢。 – 2010-05-24 15:16:04

+0

它真的说了一些关于我的精神状态时,我可以写“它偶尔成对使用(!!)将任何虚假值转换为”“和任何真值为1。在关于高优先级逻辑否定运算符的部分中,但在编写关于伪运算符的部分时完全忘记了它。也许我应该重读我的文档。 – 2010-05-24 15:24:40

1

你有两个“countof”(伪)运营商,我实在看不出它们之间的区别。

从 “countof操作者” 的例子:

my $count =()= f();    #$count is now 5 
my $string = "cat cat dog cat"; 
my $cats =()= $string =~ /cat/g; #$cats is now 3 

从 “goatse/countof操作者” 的例子:

my $count =()= f();    #$count is now 5 
my $string = "cat cat dog cat"; 
my $cats =()= $string =~ /cat/g; #$cats is now 3 

的例子两组是相同的,模空格。你认为它们是两个不同的伪操作符的理由是什么?

+0

因为有些人用不同的方式写它。这些例子并不完全相同,你省略了print print(()= f()),“\ n”; #prints“5 \ n”'不能用'=()='完成。 – 2010-05-24 17:46:49

+0

@Chas:是的,我跳过了那个,但理由很明显:'()='是什么实际工作。完整goatse上的前导'='只是将'()='生成的结果赋值给一个变量,而您在函数调用中没有这样做。说他们是不同的运营商,仅仅是因为有些人包含空白,而其他人则不同意使用不同的'+'和'='运算符来表示'1 + 1 = 2'和'1 + 1 = 2'是不同的表达式,“*因为有些人用一种方式写,而另一些用另一种方式写*”。 – 2010-05-24 22:45:47

+1

除非他们看起来像不同的操作员并有不同的描述,否则我会同意你的意见。想象一下,你不知道如何解析'my $ x =()=/a/g;',你想把'=()='单独记录下来,还是想弄清楚它是否记录在'()='?这个文档开始的最初原因是一个新手可以在perlop中找到'|| ='的文档。 – 2010-05-25 18:03:29

5

在Perl中,这些通常被称为“秘密操作员”。

部分“秘密操作员”列表can be had here。最好和最完整的名单可能拥有Philippe Bruhad aka BooK和他的Secret Perl Operators谈话,但我不知道它的可用位置。你可能会问他。你可以从Obfuscation, Golf and Secret Operators收集更多。

+0

嗯,我不知道是否值得以这种方式记录所有这些(我坦白地说,只是试图让正常的操作单独记录下来)。现在我优先考虑我期望在非obfu代码中看到的那些。 – 2010-05-24 19:48:42

3

的 “去” 与运营商 “由走近”:

$x = 10; 
say $x while $x --> 4; 
# prints 9 through 4 

$x = 10; 
say $x while 4 <-- $x; 
# prints 9 through 5 

他们不是唯一的Perl的。

+0

虽然看起来很特别,但这些东西是鼓励Obiwan错误的好方法...... :) – tsee 2010-05-25 07:50:13

+0

我发现这个操作符的SO讨论非常有趣:[这个操作符的名称是什么:“ - >”?] (http://stackoverflow.com/questions/1642028/what-is-the-name-of-this-operator) – Ether 2010-05-25 17:53:09

+0

是的,我已经看到人们之前使用过这些。 – 2010-05-25 18:26:18

3

this question,我发现%{{}}运算符将一个列表作为一个散列。 需要散列参数(而不是散列分配)的上下文中有用。

@list = (a,1,b,2); 
print values @list;  # arg 1 to values must be hash (not array dereference) 
print values %{@list}  # prints nothing 
print values (%[email protected]) # arg 1 to values must be hash (not list assignment) 
print values %{{@list}} # success: prints 12 

如果@list不包含任何重复键(奇数元素),该运营商还提供了一种方法来访问列表的奇数或偶数元素:

@even_elements = keys %{{@list}}  # @list[0,2,4,...] 
@odd_elements = values %{{@list}} # @list[1,3,5,...] 
+1

这也允许直接访问函数返回的散列元素(使用$ {{sub_name()}}:sub foo {return(a => 1,b => 2,c => 3)} print $ {{foo}} {b}; – MkV 2010-10-29 18:25:30

1

怎么样“布尔一或零”的操作符:1&!!

例如:

my %result_of = (
    " 1&!! '0 but true' " => 1&!! '0 but true', 
    " 1&!! '0'   " => 1&!! '0', 
    " 1&!! 'text'  " => 1&!! 'text', 
    " 1&!! 0   " => 1&!! 0, 
    " 1&!! 1   " => 1&!! 1, 
    " 1&!! undef  " => 1&!! undef, 
); 

for my $expression (sort keys %result_of){ 
    print "$expression = " . $result_of{$expression} . "\n"; 
} 

给出了下面的输出:

1&!! '0 but true' = 1 
1&!! '0'   = 0 
1&!! 'text'  = 1 
1&!! 0    = 0 
1&!! 1    = 1 
1&!! undef   = 0 
1

<< >>运营商,为multi-line comments

<<q==q>>; 
    This is a 
    multiline 
    comment 
q 
+1

这是错的,有一个错字:'<>;' – Matthias 2013-05-03 23:14:43

2

Perl的秘密运营商现在有一定的参考(几乎是官方的,但他们的 “秘密”)上CPAN文档: perlsecret