講座 - perl=~ g




Perlの隠された機能? (20)

新しいブロック操作

私は、言語を拡張し、擬似ブロック操作を作成する機能は1つだと言います。

  1. 最初にコード参照が必要であることを示すサブのプロトタイプを宣言します。

    sub do_stuff_with_a_hash (&\%) {
        my ( $block_of_code, $hash_ref ) = @_;
        while ( my ( $k, $v ) = each %$hash_ref ) { 
            $block_of_code->( $k, $v );
        }
    }
    
  2. あなたはそうして体の中でそれを呼び出すことができます

    use Data::Dumper;
    
    do_stuff_with_a_hash {
        local $Data::Dumper::Terse = 1;
        my ( $k, $v ) = @_;
        say qq(Hey, the key   is "$k"!);
        say sprintf qq(Hey, the value is "%v"!), Dumper( $v );
    
    } %stuff_for
    ;
    

Data::Dumper::Dumperは別のセミ隠し宝石です。)ブロックの前にsubキーワードを、ハッシュの前にカンマを必要としないことに注目してください。 それは多くのように見える終わります: map { } @list

ソースフィルタ

また、ソースフィルタもあります。 あなたがそれを操作できるようにPerlがコードを渡す場所。 これとブロック操作はどちらも、このタイプのものではありません。

私はソースフィルタを使っていくつかのすてきなことを行っています。例えば、時間をチェックするための非常に単純な言語を作成し、いくつかの意思決定のために短いPerlのone-linersを使うことができます:

perl -MLib::DB -MLib::TL -e 'run_expensive_database_delete() if $hour_of_day < AM_7';

Lib::TLは単に "変数"と定数の両方をスキャンし、それらを作成し、必要に応じてそれらを置き換えます。

ここでも、ソースフィルタは面倒ですが、強力です。 しかし、デバッガを何かひどいものにすることができます。また、警告でさえ間違った行番号で印刷することもできます。 私はDamian's Switch使用を中止しました。なぜなら、デバッガは私が実際にどこにいるか教えてくれる能力を失うからです。 しかし、コードの小さな部分を変更して同じ行に残すことで、被害を最小限に抑えることができます。

信号フック

それはしばしば十分ですが、それだけではそれほど明白ではありません。 ここには古いものをピギーバックするダイハンドラーがあります。

my $old_die_handler = $SIG{__DIE__};
$SIG{__DIE__}       
    = sub { say q(Hey! I'm DYIN' over here!); goto &$old_die_handler; }
    ;

つまり、コード内の他のモジュールが死ぬことを望むときはいつでも、あなたはあなたに来なければなりません(他の誰かが$SIG{__DIE__}上書きを上書きしない限り)。 そして、あなたは何かが何かエラーであることを通知することができます。

もちろん、十分なことがあれば、 END { }ブロックを使用することもできます。

overload::constant

あなたのモジュールを含むパッケージで特定の型のリテラルを調べることができます。 たとえば、次のimportサブフォームでこれを使用するとします。

overload::constant 
    integer => sub { 
        my $lit = shift;
        return $lit > 2_000_000_000 ? Math::BigInt->new( $lit ) : $lit 
    };

呼び出し元のパッケージ内の20億を超えるすべての整数がMath::BigIntオブジェクトに変更されることを意味します。 overload::constant参照してください。

グループ化された整数リテラル

我々はそれにしている間。 Perlでは、大きな数字を3桁のグループに分割して、解析可能な整数を引き出すことができます。 2億円以上の場合は2_000_000_000超えてください。

実際に有用ではあるが難解なPerlの言語機能は、実際に有用な仕事をするために採用することができたものは何ですか?

ガイドライン:

  • CPANではなくPerlコアへの回答を制限しようとする
  • 例と簡単な説明を記入してください

他の言語にも見られる隠れた機能 '隠し機能:

(これらはすべてコリオンの答えです

  • C
    • ダフのデバイス
    • 移植性と標準性
  • C#
    • 空白で区切られたリストと文字列の引用
    • 別名可能な名前空間
  • Java
    • スタティック・イニシアティブ
  • JavaScript
    • 機能はファーストクラスの市民です
    • ブロック範囲とクロージャ
    • 変数を通じて間接的にメソッドとアクセサを呼び出す
  • Ruby
    • コードによるメソッドの定義
  • PHP
    • Pervasiveオンラインマニュアル
    • マジックメソッド
    • シンボリックリファレンス
  • Python
    • 1行の値の交換
    • コア機能を自分の機能で置き換える機能

その他の隠された特徴:

オペレーター:

引用構文:

構文と名前:

モジュール、プラグマ、およびコマンドラインオプション:

変数:

ループとフロー制御:

正規表現:

その他の機能:

その他のトリック、およびメタ回答:

関連項目:


"for"ステートメントは、 "with"がパスカルで使用されるのと同じ方法で使用できます。

for ($item)
{
    s/&‎nbsp;/ /g;
    s/<.*?>/ /g;
    $_ = join(" ", split(" ", $_));
}

変数名を繰り返すことなく、同じ変数に一連のs ///操作などを適用できます。

注:マークアップを回避するために、上記の区切り記号のないスペース(&nbsp;)にUnicodeが隠されています。 貼り付けはしないでください:)


Perlではほとんどあらゆる種類の奇妙な文字列を引用するのは簡単です。

my $url = q{http://my.url.com/any/arbitrary/path/in/the/url.html};

実際、Perlのさまざまな引用機構はかなり面白いです。 Perlの正規表現のような引用機構は、区切り文字を指定して何かを引用することを可能にします。 #、/、または()、[]、または{}のようなオープン/クローズ文字のようなほとんどすべての特殊文字を使用できます。 例:

my $var  = q#some string where the pound is the final escape.#;
my $var2 = q{A more pleasant way of escaping.};
my $var3 = q(Others prefer parens as the quote mechanism.);

引用メカニズム:

q:リテラル引用。 エスケープする必要のある文字のみが終了文字です。 qq:解釈された見積もり。 変数とエスケープ文字を処理します。 あなたが引用する必要がある文字列のための素晴らしい:

my $var4 = qq{This "$mechanism" is broken.  Please inform "$user" at "$email" about it.};

qx:qqのように動作しますが、対話的にではなくシステムコマンドとして実行します。 標準出力から生成されたすべてのテキストを返します。 (OSでサポートされている場合はリダイレクトも出てくる)バッククォート( `文字)で終わる。

my $output  = qx{type "$path"};      # get just the output
my $moreout = qx{type "$path" 2>&1}; # get stuff on stderr too

qr:qqのように解釈しますが、それを正規表現としてコンパイルします。 正規表現のさまざまなオプションも使用できます。 正規表現を変数として渡すことができます:

sub MyRegexCheck {
    my ($string, $regex) = @_;
    if ($string)
    {
       return ($string =~ $regex);
    }
    return; # returns 'null' or 'empty' in every context
}

my $regex = qr{http://[\w]\.com/([\w]+/)+};
@results = MyRegexCheck(q{http://myurl.com/subpath1/subpath2/}, $regex);

qw:非常に便利な見積り演算子です。 指定された空白で区切られた単語の集合をリストに変換します。 単体テストでデータを入力するのに最適です。


   my @allowed = qw(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z { });
   my @badwords = qw(WORD1 word2 word3 word4);
   my @numbers = qw(one two three four 5 six seven); # works with numbers too
   my @list = ('string with space', qw(eight nine), "a $var"); # works in other lists
   my $arrayref = [ qw(and it works in arrays too) ]; 

物事をより明確にするたびにそれらを使うのは素晴らしいことです。 qx、qq、qについては、{}演算子を使用する可能性が最も高いです。 qwを使用する人々の最も一般的な習慣は、通常は()演算子ですが、時にはqw //も参照することがあります。


Perlには多くの非自明な機能があります。

たとえば、一節の後にスペースができることを知っていますか?

 $ perl -wle 'my $x = 3; print $ x'
 3

または、シンボリックリファレンスを使用する場合は、サブ名の数値を指定できますか?

$ perl -lwe '*4 = sub { print "yes" }; 4->()' 
yes

真の式には1を返し、falseには空の文字列を返す "ブール"準演算子もあります。

$ perl -wle 'print !!4'
1
$ perl -wle 'print !!"0 but true"'
1
$ perl -wle 'print !!0'
(empty line)

その他の興味深いもの: use overloadロードでは、文字列のリテラルや数値をオーバーuse overloadすることができます(たとえば、BigIntsなど)。

これらの事の多くは、実際に文書化されているか、文書化された機能から論理的に従っていますが、あまりよく知られていないものもあります。

更新 :別の素晴らしい1つ。 q{...}引用構文が書かれていましたが、区切り文字として文字を使用できることはご存じですか?

$ perl -Mstrict  -wle 'print q bJet another perl hacker.b'
Jet another perl hacker.

同様に、正規表現を書くこともできます:

m xabcx
# same as m/abc/

Perlは他のリストからほとんどすべての "難解な"部分を持っているので、私はあなたにPerlができないことを教えてくれるでしょう:

Perlができないことの1つは、 //演算子が正規表現に使用されるため、あなたのコードに裸の任意のURLがあることです。

ちょうどあなたがPerlが提供している機能が明らかでない場合に備えて、完全にはっきりしないエントリの選択リストがあります:

ダフのデバイス - Perlで

移植性と標準性 - Perlを使用するコンピュータはCコンパイラよりも多い可能性があります

ファイル/パス操作クラス - File :: Findは.Netよりもさらに多くのオペレーティングシステムで動作します

空白で区切られたリスト と文字列の 引用 - Perlでは、あなたのリストと文字列区切り文字のほとんど任意の引用符を選ぶことができます

エイリアス可能な名前空間 - Perlにはglob 単位の代入があります:

*My::Namespace:: = \%Your::Namespace

静的イニシャライザ - PerlはBEGIN (コード解析)からCHECK (コード解析後)から(モジュールインポート時)からnew (オブジェクトインスタンス化)へのDESTROY (オブジェクト破壊)までのコンパイルとオブジェクトインスタンス化のほぼすべてのフェーズでコードを実行できます。 END (プログラム出口)

関数は Perlのようにファーストクラスの市民です

ブロックスコープとクロージャ - Perlには両方があります

変数を通して間接的にメソッドやアクセサを呼び出す - Perlもそうします:

my $method = 'foo';
my $obj = My::Class->new();
$obj->$method( 'baz' ); # calls $obj->foo( 'baz' )

コードでメソッドを定義する - Perlでも可能です

*foo = sub { print "Hello world" };

Pervasiveオンラインドキュメント - Perlドキュメントはオンラインであり、システム上にある可能性もあります

"存在しない"関数を呼び出すたびに呼び出されるマジックメソッド - PerlはAUTOLOAD関数でそのメソッドを実装しています

記号的な言葉 - あなたはこれらから遠ざかることを勧めます。 彼らはあなたの子供を食べます。 もちろん、Perlはあなたの子供を血の渇きの悪魔に捧げることを可能にします。

1行の値の交換 - Perlはリストの割り当てを許可します

コア機能を自分の機能で置き換える機能

use subs 'unlink'; 
sub unlink { print 'No.' }

または

BEGIN{
    *CORE::GLOBAL::unlink = sub {print 'no'}
};

unlink($_) for @ARGV


BEGINCHECKおよびのような特別なコードブロックEND。彼らはAwkから来ていますが、Perlではレコードベースではないため、動作が異なります。

このBEGINブロックは、解析フェーズ用のコードを指定するために使用できます。構文と変数のチェックを行うときにも実行されますperl -c。たとえば、構成変数をロードするには、次のようにします。

BEGIN {
    eval {
        require 'config.local.pl';
    };
    if ([email protected]) {
        require 'config.default.pl';
    }
}

"-n""-p"スイッチがPerl 5で実装されている方法に基づいて、 }{

ls |perl -lne 'print $_; }{ print "$. Files"'

これは内部的にこのコードに変換されます:

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

魔法のARGVを介して圧縮ファイルのサポートを追加する:

s{ 
    ^            # make sure to get whole filename
    ( 
      [^'] +     # at least one non-quote
      \.         # extension dot
      (?:        # now either suffix
          gz
        | Z 
       )
    )
    \z           # through the end
}{gzcat '$1' |}xs for @ARGV;

(シェルメタキャラクタでファイル名を扱うために必要な$ _の前後の引用符)

今すぐ<>機能は、 ".gz"または ".Z"で終わる@ARGVファイルをすべて解凍します:

while (<>) {
    print;
}

DATAブロックに直接貼り付けられたデータを解析する機能。 プログラムなどで開くテストファイルに保存する必要はありません。 例えば:

my @lines = <DATA>;
for (@lines) {
    print if /bad/;
}

__DATA__
some good data
some bad data
more good data 
more good data 

これはコードをより表現力豊かにするだけでなく、この「関数型プログラミング」についてもう少し詳しく読むためのインパルスを与えたからです。


これはメタアンサーですが、 Perl Tipsアーカイブには、 Perlで行うことができる興味深いあらゆる種類のトリックが含まれています。 以前のヒントのアーカイブは、閲覧のためにオンラインであり、メーリングリストまたはアトムフィードを介して購読することができます。

私の好きなヒントのいくつかは、 PAR実行可能ファイル をビルドするオートデイを使用して例外を自動的にスローする方法、Perl 5.10でswitchsmart-matchコンストラクトを使用する方法などがあります。

開示:私はPerl Tipsの作成者とメンテナーの一人です私は明らかにそれらを非常に高く評価しています。 ;)


フリップフロップ演算子は、フラグ変数を使用せずに、ファイルハンドルによって返されたレコード(通常は行)をループするときに最初の繰り返しをスキップするのに便利です。

while(<$fh>)
{
  next if 1..1; # skip first record
  ...
}

perldoc perlopを実行し、詳細と例については "flip-flop"を検索してください。


ループのcontinue句 これは、すべてのループの最後で実行されます。

while( <> ){
  print "top of loop\n";
  chomp;

  next if /next/i;
  last if /last/i;

  print "bottom of loop\n";
}continue{
  print "continue\n";
}

少し不明なのは、スカラーコンテキストを強制するチルダ - チルダ "演算子"です。

print ~~ localtime;

〜と同じです

print scalar localtime;

異なる

print localtime;

引用符演算子は私の好きなものの一つです。 比較:

my @list = ('abc', 'def', 'ghi', 'jkl');

そして

my @list = qw(abc def ghi jkl);

ノイズが少なく、目には簡単です。 SQLを書くときに本当に見逃している、Perlに関するもう1つの本当に良い点は、末尾のカンマが合法だということです。

print 1, 2, 3, ;

これは奇妙に見えますが、コードを別の方法でインデントした場合はそうではありません。

print
    results_of_foo(),
    results_of_xyzzy(),
    results_of_quux(),
    ;

関数呼び出しに追加の引数を追加しても、前または後ろの行でカンマで囲む必要はありません。 1行の変更は周囲の行には影響しません。

これにより、多様な関数を扱うことが非常に楽しいものになります。 これはおそらくPerlの最も評価の低い機能の1つです。


汚れチェック。 汚染されたデータ(おおまかに言えば、プログラムの外部のデータ)を安全でない関数(ファイルを開く、外部コマンドを実行するなど)に渡そうとすると、perlは汚染検査を有効にすると、 。 これは、setuidスクリプトやCGI、またはスクリプトがデータを送る人よりも大きな特権を持つ場合は、非常に役に立ちます。

マジックジャンプ。 goto &subは最適化されたテールコールを行います。

デバッガ。

use strictuse warningsuse warnings 。 これらはタイプミスからあなたを救うことができます。


私の投票は、Perlの正規表現の(?{})グループと(?? {})グループになります。 最初のコードはPerlコードを実行し、戻り値は無視し、2番目のコードは戻り値を正規表現として使用してコードを実行します。


空のfilehandle ダイヤモンド演算子 <>は、ビルドコマンドラインツールでその場所を持っています。<FH>コマンドラインのファイル名やSTDINのように最初から見つかったものを魔法のように選択するという点を除いて、ハンドルから読み取るように動作します。perlopから取られた:

while (<>) {
...         # code for each line
}

rename("$_.part", $_) for "data.txt";

自分自身を繰り返すことなくdata.txt.partの名前をdata.txtに変更します。





hidden-features