2010-05-24 1 views
27

В настоящее время я документирую все операторы Perl 5 (см. Проект GitHub perlopref), и я решил включить в него псевдооператоры 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 –

+0

Что насчет '+ =', '- =', '/ =', '* =', '** =' семейства и коротких сообщений, операторы цепей '|| = или // ='? Являются ли они псевдооперациями? – Zaid

+0

@ Zaid no, это действительно операторы. Они документируются в разделе «Операторы присваивания» (http://perldoc.perl.org/perlop.html#Assignment-Operators) в perlop и индивидуально в моем документе. –

ответ

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

+0

Crap, я забыл все о !! bool op. Я не знаю, действительно ли +0 и. '', Но я думаю, что нет никакого вреда в их добавлении. Интерполяционные трюки являются определенными. Я никогда не рассматривал использование оператора повторения таким образом, это тоже определенные дополнения. Благодарю. –

+0

Это действительно говорит о моем психическом состоянии, когда я могу написать «Иногда он используется парами (!!), чтобы преобразовать любое ложное значение в« »и любое истинное значение в 1.» в разделе об операторе логического отрицания с высоким приоритетом, но забывайте об этом полностью при написании раздела о псевдооператорах. Возможно, я должен перечитать мой документ. –

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 scalar (() = f()),« \ n »; #prints "5 \ n" ', который нельзя сделать с помощью' =() = '. –

+0

@ Час .: Да, я пропустил этот, но рассуждал так же очевидно: '() =' это то, что делает фактическая работа. Ведущий '=' на полном коассе просто присваивает результат, сгенерированный '() =' переменной, которую вы не выполняете в вызове функции. Говоря, что они разные операторы только потому, что некоторые люди включают пробелы, а другие не говорят, что «1 + 1 = 2» и «1 + 1 = 2» - это разные выражения, используя разные операторы '+' и '=' , «* потому что некоторые люди пишут это в одну сторону, а другие - по-другому». –

+1

Я согласен с вами, кроме факта, что они выглядят как разные операторы и имеют разные описания. Представьте, что вы не знаете, как разбирать 'my $ x =() =/a/g;', вы бы предпочли бы '=() =' быть документированы отдельно или хотите попытаться выяснить, что оно описано в '() ='? Первоначальная причина этого документа была начата в том, что новичок мог найти документы для '|| =' в perlop. –

5

В Perl они обычно называются «секретными операторами».

Частичный список «секретных операторов» can be had here. Самый лучший и самый полный список - это, вероятно, Philippe Bruhad aka BooK и его обсуждение Secret Perl Operators, но я не знаю, где его можно найти. Вы можете спросить его. Вероятно, вы можете почерпнуть еще от Obfuscation, Golf and Secret Operators.

+0

Хмм, я не знаю, стоит ли документировать их все таким образом (я откровенно измучен, просто пытаясь получить нормальные документы, задокументированные отдельно). Прямо сейчас я отдаю приоритет тем, которые я ожидаю увидеть в коде, отличном от obfu. –

3

Не забудьте указать Flaming X-Wing=<>=~.

Список рассылки Fun With Perl окажется полезным для ваших исследований.

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

+0

Я нашел SO обсуждение этого оператора очень интересным: [Как называется этот оператор: "->"?] (http://stackoverflow.com/questions/1642028/what-is-the-name-of-this-operator) – Ether

+0

Да, я определенно видел, как люди используют их раньше. –

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

1

Как насчет «Boolean один или нулевой»оператор: 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 
2

В Perl секретные операторы получили некоторые ссылки (почти официальной, но они "секрет") документации на CPAN: perlsecret

Смежные вопросы