Perlプログラミング言語の構造は、言語の構文規則とプログラムの構成方法の両方を含みます。Perl の設計思想は、よく引用されるモットー「やり方は一つではない」に表されています。マルチパラダイムで動的型付け言語である Perl は、プログラム設計において非常に高い柔軟性を提供します。Perl はモジュール化も推奨しており、これは Unix のコンポーネントベースの設計構造に起因するとされています[ 1 ] 。また、10 万を超えるモジュールをコミュニティが管理するリポジトリであるCPANアーカイブの規模の大きさにも関係しています[ 2 ] 。
Perlでは、最小限のHello Worldプログラムは次のように記述できます。
「こんにちは、世界!」と印刷するこれは「Hello, World!」という文字列と改行文字を出力します。改行文字は、直前のエスケープ文字(バックスラッシュ)によって解釈が変わる文字で象徴的に表現されます。バージョン5.10以降、新しい組み込み関数「say」[ 3 ]を使用すると、同じ効果をさらに簡単に実現できます。n
「こんにちは、世界!」と言ってみよう!Perlプログラム全体をコマンドラインパラメータとして指定することもできるため、同じプログラムをコマンドラインから実行することも可能です(Unixの例を示します)。
$ perl -e ' print "Hello, World!\n"'プログラムの標準形式は、やや冗長です。
#!/usr/bin/env perl print "Hello, World!\n" ;Perl では、ハッシュ記号 (#) はコメントの導入文字であり、コード行の末尾まで記述され、コンパイラによって無視されます(Windows を除く)。ここで使用されているコメントは特殊なもので、シェバン行と呼ばれます。これは、Unix 系オペレーティングシステムに Perl インタープリタを見つけるように指示し、明示的に指定しなくてもプログラムを呼び出すことを可能にしますperl。( Microsoft Windowsシステムでは、Perl プログラムは通常、.pl拡張子をPerl インタープリタに関連付けることで呼び出されることに注意してください。このような状況に対処するため、perlはシェバン行を検出し、スイッチを解析します。[ 4 ] )
標準形式の2行目にはセミコロンが含まれていますが、これはPerlでステートメントを区切るために使用されます。ブロックまたはファイル内にステートメントが1つしかない場合は、区切り文字は不要なので、プログラムの最小形式、あるいはより一般的には任意のブロックまたはファイルの最後のステートメントから省略できます。標準形式にセミコロンが含まれているのは、不要な場合でもすべてのステートメントを終了させるのが一般的であるためです。これにより編集が容易になり、セミコロンを調整することなく、コードをブロックまたはファイルの末尾に追加したり、そこから移動したりできます。
Perlのバージョン5.10では、say出力に改行文字を暗黙的に追加する関数が導入され、最小限の「Hello World」プログラムがさらに短くなりました。
use 5.010 ; # 新しい 5.10 関数をインポートするには、これが存在する必要があります。5.10 ではなく 5.010 であることに注意してください。say 'Hello, World!'Perlにはいくつかの基本的なデータ型があります。最もよく使われ、議論されるのは、スカラー、配列、ハッシュ、ファイルハンドル、サブルーチンです。
文字列値(リテラル)は引用符で囲む必要があります。文字列を二重引用符で囲むと、文字列内に含まれる変数名の値が自動的に文字列内の変数名に置き換えられます(または補間されます)。文字列を単一引用符で囲むと、変数の補間は行われません。
例えば、次$nameの場合"Jim":
print("My name is $name")が出力されます。"My name is Jim"print('My name is $name')と表示されます。"My name is $name"文字列に二重引用符を含めるには、二重引用符の前にバックスラッシュを付けるか、文字列を単一引用符で囲みます。単一引用符を含めるには、二重引用符の前にバックスラッシュを付けるか、文字列を二重引用符で囲みます。
q文字列は、引用符のような演算子を使って引用符で囲むこともできますqq。
'this'そしてq(this)同一である、"$this"そして、qq($this)それらは同一である。最後に、複数行の文字列は、ヒアドキュメントを使用して定義できます。
$multilined_string = << EOF ;これは私の複数行文字列です。「EOF」という単語で終了していることに注意してください。EOF数値(数値定数)は引用符を必要としません。Perl は、使用されるコンテキストに応じて数値を文字列に、またはその逆に変換します。文字列を数値に変換する場合、文字列の末尾の非数値部分は破棄されます。文字列の先頭に数値がない場合、文字列は数値 0 に変換されます。次の例では、文字列$nとが$m数値として扱われます。このコードは数値 '5' を出力します。変数の値は変わりません。Perl では、+は常に数値加算演算子であることに注意してください。文字列連結演算子はピリオドです。
$n = '3 apples' ; $m = '2 oranges' ; print $n + $m ;小数値を整数に丸めるための関数が用意されています。小数部分intを切り捨ててゼロ方向に丸め、常に切り上げ、常に切り捨てます。数値を文字列に変換する場合、偶数に丸める場合は銀行の丸めを使用します。POSIX::ceilPOSIX::floorprintf "%f"sprintf "%f"
Perlには、条件文を評価する際に使用するブール型のコンテキストもあります。Perlでは、以下の値はすべて偽と評価されます。
$false = 0 ; # 数値ゼロ$false = 0.0 ; # 浮動小数点数としての数値ゼロ$false = 0b0 ; # 数値ゼロのバイナリ$false = 0x0 ; # 数値ゼロの16進数$false = '0' ; # 文字列ゼロ$false = "" ; # 空文字列$false = (); # 空リスト$false = undef ; # undef の戻り値$false = 2 - 3 + 1 # 計算結果は 0 で、"0" に変換されるため false になりますその他の (評価値がゼロでない) 値はすべて true と評価されます。これには、実際には数値としては 0 ですが、ブール値として使用すると true になる、奇妙な自己記述リテラル文字列 "0 but true" も含まれます。すべての非数値文字列もこの特性を持ちますが、この特定の文字列は数値警告なしに Perl によって切り捨てられます。この文字列の、明示的ではないが概念的に移植性の高いバージョンは ' 0E0 ' または ' 0e0 ' です。これは、文字が 0 と評価されることに依存しません。なぜなら、'0E0' は文字通り 0 に 10 の 0 乗を掛けたものだからです。空のハッシュも true です。このコンテキストでは、は空のブロックではありません。なぜなら、が を返すからです。{}{}perl -e 'print ref {}'HASH
評価されたブール式もスカラー値です。ドキュメントでは、 true または false のどの特定の値が返されるかは保証されていません。多くのブール演算子は、true の場合は 1 を、false の場合は空文字列を返します。このdefined()関数は、変数に値が設定されているかどうかを判定します。上記の例では、 をdefined($false)除くすべての値に対して true になりますundef。
1または0のいずれかが特に必要な場合は、条件演算子を使用して明示的な変換を行うことができます。
my $real_result = $boolean_result ? 1 : 0 ;配列の値(またはリスト)は、要素をカンマで区切り、括弧で囲むことによって指定します(少なくとも演算子の優先順位で必要な場合)。
@scores = ( 32 , 45 , 16 , 5 );qw() という引用符のような演算子を使うと、引用符やカンマを入力せずに文字列のリストを定義できます。括弧の代わりにほぼすべての区切り文字を使用できます。以下の行は同等です。
@names = ( 'Billy' , 'Joe' , 'Jim-Bob' ); @names = qw(Billy Joe Jim-Bob) ;split関数は、区切り文字列または正規表現を使用して文字列式から分割された文字列のリストを返します。
@scores = split ( ',' , '32,45,16,5' );リストの個々の要素には、角括弧で囲んだ数値インデックスを指定することでアクセスできます。スカラー記号を使用する必要があります。サブリスト(配列スライス)も、括弧で囲んだ数値インデックスの範囲またはリストを使用して指定できます。この場合、配列記号を使用します。たとえば、$month[3]は"April"(配列の最初の要素のインデックス値は 0 です)、@month[4..6]は です("May", "June", "July")。
Perl プログラマーは、キーと値のペアのリストからハッシュ (または連想配列=>) を初期化できます。キーと値がカンマではなく演算子 (ファット カンマと呼ばれることもあります) で区切られている場合、キーは引用符なしで使用できます (ベアワード[ 5 ] )。次の行は同等です。
%favorite = ( 'joe' , "red" , 'sam' , "blue" ); %favorite = ( joe => 'red' , sam => 'blue' );ハッシュ内の個々の値にアクセスするには、対応するキーを中括弧で囲みます。$シジルは、アクセスする要素がスカラーであることを示します。たとえば、$favorite{joe}は に等しくなります'red'。ハッシュは、値を個別に設定することによって初期化することもできます。
$favorite { joe } = 'red' ; $favorite { sam } = 'blue' ; $favorite { oscar } = 'green' ;複数の要素には、代わりにシジルを使用してアクセスできます@(結果をリストとして識別します)。たとえば、 @favorite{'joe', 'sam'}は に等しくなります('red', 'blue')。
ファイルハンドルは、リソースへの読み書きアクセスを提供します。これらは多くの場合、ディスク上のファイルですが、デバイス、パイプ、あるいはスカラー値である場合もあります。
当初、ファイルハンドルはパッケージ変数でのみ作成でき、他の変数と区別するためにすべて大文字の表記規則が用いられていました。Perl 5.6以降では、スカラー変数も使用可能になり、名前付きファイルハンドルの代わりに、匿名ファイルハンドルへの参照が設定されます(自動的に設定されます)。
タイプグロブ値はシンボルテーブルのエントリです。タイプグロブの主な用途は、シンボルテーブルのエイリアスを作成することです。例:
* PI = \ 3.141592653 ; # 定数スカラー $PI を作成* this = * that ; # すべてのデータ型 'this' からすべてのデータ型 'that' へのエイリアスを作成配列の要素数は、スカラーコンテキストで配列を評価するか、$#シジルを使用して決定できます。後者は、配列の最後の要素のインデックスを示し、要素数ではありません。式 scalar( @array) と ( ) は同等です。$#array + 1
ハッシュ全体を操作する関数がいくつかあります。`keys`関数はハッシュを受け取り、そのキーのリストを返します。同様に、 ` values`関数はハッシュの値を返します。キーと値は、一貫性はあるものの、任意の順序で返されることに注意してください。
# each を呼び出すたびに、次のキー/値ペアが返されます。# 最終的にはすべての値が返されますが、その順序は予測できません。while (( $name , $address ) = each %addressbook ) { print "$name は $address に住んでいます\n" ; }# 上記と同様だが、アルファベット順にソートするforeach my $next_name ( sort keys %addressbook ) { print "$next_name は $addressbook{$next_name} に住んでいます\n" ; }Perlにはいくつかの種類の制御構造がある。
C、 JavaScript、Javaなどのプログラミング言語と同様に、ブロック指向の制御構造を採用しています。条件は括弧で囲まれ、制御ブロックは中括弧で囲まれます。
label while ( cond ) { ... } label while ( cond ) { ... } continue { ... } label for ( init-expr ; cond-expr ; incr-expr ) { ... } label foreach var ( list ) { ... } label foreach var ( list ) { ... } continue { ... } if ( cond ) { ... } if ( cond ) { ... } else { ... } if ( cond ) { ... } elsif ( cond ) { ... } else { ... }単一のステートメントのみを制御する場合、ステートメント修飾子を使用すると、より簡潔な構文が得られます。
条件が満たされる場合のステートメント; 条件が満たされない場合のステートメント; 条件が満たされる間ステートメント; 条件が満たされるまでのステートメント; リストごとにステートメント;
短絡論理演算子は、式レベルで制御フローに影響を与えるためによく使用されます。
exprとexpr expr && expr exprまたはexpr expr || expr(「and」演算子と「or」演算子は、&&演算子と||演算子に似ていますが、優先順位が低いため、ステートメント全体を制御するのに使いやすくなっています。)
フロー制御キーワードnext(C の に対応continue)、last(C の に対応break)、、returnおよびredoは式なので、短絡演算子と一緒に使用できます。
Perlには、それぞれ2つの形式を持つ2つの暗黙的なループ構造も存在する。
結果= grep { ... }リスト結果= grep expr、リスト結果= map { ... }リスト結果= map expr、リストgrep制御ブロックまたは式が真と評価されるリストのすべての要素を返します。リストmapの各要素に対して制御ブロックまたは式を評価し、結果の値のリストを返します。これらの構造により、シンプルな関数型プログラミングスタイルが可能になります。
Perl 5 では、5.10.0 リリースまではswitch 文はgiven存在しませんでした。5.10.0 以降では、 /と呼ばれる多分岐文がwhen利用可能になり、以下の形式をとります。
usev5.10;# must be present to import the new 5.10 functions given ( expr ) { when ( cond ) { ... } default { ... } }構文的には、この構造は他の言語のswitch 文と似たような動作をしますが、いくつか重要な違いがあります。最も大きな違いは、switch/case 構造とは異なり、given/when 文は明示的に定義された break コマンドを待つのではなく、最初の分岐が成功した後に実行を中断することです。逆に、continueswitch の動作をエミュレートするには、明示的な break が必要です。
Perl 5.10 を使用していないユーザー向けに、Perl のドキュメントには、他の制御構造を使用して同じ効果を実現する方法が 6 つほど記載されています。また、姉妹言語であるRakuの機能に似た機能を提供する Switch モジュールもあります。これはソースフィルタを使用して実装されているため、非公式には使用が推奨されていません。[ 6 ]
Perlには` goto labelif`文が含まれていますが、ほとんど使用されません。goto他の言語で`if`文が必要となるような状況は、Perlの豊富なフロー制御オプションのおかげで、Perlではあまり発生しません。
末尾呼び出しを実行するステートメントもあります。これは現在のサブルーチンを終了し、指定された関数を即座に呼び出します。これは、呼び出し元が Perl 自体よりも効率的なスタック管理を実行できる場合 (通常は現在のスタックに変更を加える必要がないため) に使用され、深い再帰では、戻り時のスコープ/スタック管理のオーバーヘッドを回避するため、末尾呼び出しはパフォーマンスに大きなプラスの影響を与える可能性があります。goto &subsub
サブルーチンはキーワードで定義されsub、名前を付けるだけで呼び出されます。対象のサブルーチンがまだ宣言されていない場合は、関数名の後に括弧を付けるか、関数名の前にアンパサンド(&)を付ける必要があります。ただし、括弧なしで&を使用すると、現在のサブルーチンの引数が呼び出されるサブルーチンに暗黙的に渡され、括弧付きで&を使用すると、プロトタイプが無視されます。
# サブルーチンの呼び出し# サブルーチンがコードの後半で定義されている場合は、ここで括弧が必要ですfoo (); & foo ; # (これも機能しますが、サブルーチンに渡される引数に関して他の影響があります)# サブルーチンの定義sub foo { … }foo ; # ここでは括弧は不要ですサブルーチン名の後に引数リストを指定できます。引数はスカラー値、リスト、またはハッシュ値のいずれかです。
foo $x 、@y 、%z ;サブルーチンの引数は、数や型を宣言する必要はありません。実際、引数は呼び出しごとに異なっても構いません。引数の検証は、サブルーチン内で明示的に行う必要があります。
配列は要素に展開され、ハッシュはキーと値のペアのリストに展開され、それらすべてがスカラーのフラットなリストとしてサブルーチンに渡されます。
渡された引数はすべて、特別な配列に格納され、サブルーチンで使用できます@_。 の要素は@_実際の引数への参照であり、 の要素を変更すると、@_対応する引数も変更されます。
の要素に@_は、通常の方法で添え字を使ってアクセスできます。
$_ [ 0 ], $_ [ 1 ]しかし、結果として得られるコードは読みにくくなる可能性があり、パラメータは参照渡しとなるため、望ましくない場合もある。
@_よく使われる慣用表現の一つに、名前付き変数のリストに値を代入する方法がある。
my ( $x , $y , $z ) = @_ ;これにより、覚えやすいパラメータ名が提供され、値渡しセマンティクスが実装されます。myキーワードは、後続の変数が包含ブロックの字句スコープを持つことを示します。
もう一つの慣用表現は、パラメータを からシフトすることです@_。これは、サブルーチンが引数を 1 つだけ取る場合や、$selfオブジェクト指向モジュールで引数を処理する場合によく用いられます。
my $x = shift ;サブルーチンは@_ハッシュに代入して名前付き引数をシミュレートすることができます。これは、3 つ以上のパラメータを持つ可能性のあるサブルーチンに対してPerl のベストプラクティスで推奨されています。 [ 7 ]
sub function1 { my %args = @_ ; print "'x' 引数は '$args{x}' でした\n" ; } function1 ( x => 23 );サブルーチンは値を返す場合があります。
return 42 , $x , @y , %z ;サブルーチンが終了return条件文で終了しない場合、サブルーチン本体内で最後に評価された式が返されます。戻り値に含まれる配列やハッシュは、引数の場合と同様に、スカラー値のリストに展開されます。
返された式は、サブルーチンの呼び出しコンテキストで評価されます。これは、注意していない人にとっては意外なことかもしれません。
サブリスト{ ( 4 , 5 , 6 ) }サブ配列{ @x = ( 4 , 5 , 6 ); @x }$x = list ; # リストの最後の要素である 6 を返します$x = array ; # リスト内の要素数である 3 を返します@x = list ; # (4, 5, 6) を返します@x = array ; # (4, 5, 6) を返しますサブルーチンは、wantarray関数を使用して呼び出しコンテキストを検出できます。
sub either { return wantarray ? ( 1 , 2 ) : 'Oranges' ; }$x = either ; # "Oranges" を返します@x = either ; # (1, 2) を返しますPerl 5は匿名関数をサポートしています[ 8 ]。以下のようにです。
( sub { print "I got called\n" }) -> (); # 1. 完全に匿名で、作成されたとおりに呼び出されますmy $squarer = sub { my $x = shift ; $x * $x }; # 2. 変数に代入sub curry { my ( $sub , @args ) = @_ ; return sub { $sub -> ( @args , @_ ) }; # 3. 別の関数の戻り値として}# Perlプログラミングにおけるカリー化の例sub sum { my $tot = 0 ; $tot += $_ for @_ ; $tot } # 引数の合計を返しますmy $curried = curry \& sum , 5 , 7 , 9 ; print $curried -> ( 1 , 2 , 3 ), "\n" ; # 27 ( = 5 + 7 + 9 + 1 + 2 + 3 ) を出力します他の構造では、引数としてベアブロックを受け取ります。これは、1 つのパラメータを持つラムダ関数と同様の機能を持ちますが、関数と同じパラメータ渡し規則はありません (@_ は設定されません)。
my @squares = map { $_ * $_ } 1 .. 10 ; # map と grep は 'sub' キーワードを使用しませんmy @square2 = map $_ * $_ , 1 .. 10 ; # 1 つの式には中括弧は不要ですmy @bad_example = map { print for @_ } 1 .. 10 ; # 通常の Perl 関数のように値が渡されないPerl言語には正規表現(RE、またはregex)を記述するための専用構文があり、インタプリタには文字列を正規表現に照合するエンジンが搭載されています。この正規表現エンジンはバックトラッキングアルゴリズムを使用しており、単純なパターンマッチングから文字列のキャプチャと置換まで、その機能を拡張しています。この正規表現エンジンは、 Henry Spencer氏が作成したregexをベースにしています。
Perl の正規表現構文は、元々は Unix バージョン 8 の正規表現から取られたものです。しかし、Perl の最初のリリース前に分岐し、その後、はるかに多くの機能を含むように成長しました。PHP、Ruby、Java、Microsoft の .NET Framework [ 9 ]、Apache HTTP サーバーなど、他の多くの言語やアプリケーションが、 POSIX正規表現よりもPerl互換正規表現を採用しています。
正規表現の構文は、その歴史的背景から非常に簡潔です。初期の正規表現はグロブパターンよりもわずかに表現力が高い程度で、構文は一致するテキストに似た表現になるように設計されていました。つまり、サポートされている数少ないアサーションを表現するために、句読点1文字または区切り文字2文字しか使用できなかったのです。時が経つにつれ、正規表現の表現力は飛躍的に向上しましたが、構文設計は改訂されることなく、句読点に依存し続けています。そのため、正規表現は難解で非常に複雑なものになりがちです。
(match)演算子m//は正規表現のマッチを導入します。(ここに示すすべての例のようにスラッシュで区切られている場合は、m簡潔にするために先頭の を省略できます。m以下のすべての例のように が存在する場合は、スラッシュの代わりに他の区切り文字を使用できます。) 最も単純なケースでは、次のような式が
$x =~ /abc/ ;文字列が正規表現に一致する場合にのみ真と評価されます。$xabc
s///一方、(置換)演算子は、検索置換操作を指定します。
$x =~ s/abc/aBc/ ; # b を大文字にする正規表現のもう1つの用途は、split関数の区切り文字を指定することです。
@words = split /,/ , $line ;このsplit関数は、正規表現に一致する部分で区切られた文字列の各部分をリスト化します。この例では、1行がカンマで区切られた複数の部分に分割され、そのリストが配列に格納されます@words。
Perlの正規表現は修飾子を取ることができます。これらは、式の意味を変更する1文字の接尾辞です。
$x =~ /abc/i ; # 大文字小文字を区別しないパターンマッチ$x =~ s/abc/aBc/g ; # グローバル検索と置換正規表現は簡潔な構文のため、コードが複雑で難解になりがちであるため、プログラマーがより読みやすい正規表現を記述できるように、Perl には修飾子が追加されました。この修飾子を使用すると、正規表現の中に/x空白やコメントを挿入できます。
$x =~ / a # 'a' にマッチします。 # 任意の文字c # その後に 'c' 文字が続きます/x ;正規表現の一部は括弧で囲むことができます。一致する文字列の対応する部分がキャプチャされます。キャプチャされた文字列は、連続する組み込み変数に代入され$1, $2, $3, …、キャプチャされた文字列のリストが一致の値として返されます。
$x =~ /a(.)c/ ; # 'a' と 'c' の間の文字をキャプチャしますキャプチャした文字列は、$1, $2, $3, …後々のコード内で使用できます。
Perlの正規表現では、修飾子を使用することで、組み込み関数またはユーザー定義関数をキャプチャされたマッチに適用することもできます/e。
$x = "Oranges" ; $x =~ s/(ge)/uc($1)/e ; # OranGEs $x .= $1 ; # 前のステートメントで一致した内容を $x に追加します: OranGEsgePerlでオブジェクト指向コードを書く方法は数多くあります。最も基本的な方法は、「祝福された」参照を使うことです。これは、任意の型の参照を特定のパッケージに属するものとして識別し、そのパッケージが祝福された参照に対応するメソッドを提供することで機能します。例えば、2次元の点は次のように定義できます。
sub Point ::new { # ここで、Point->new(4, 5) を実行すると、$class は 'Point' になります。# これはサブクラス化をサポートするための変数です (perloop の man ページを参照してください)。my ( $class , $x , $y ) = @_ ; bless [ $x , $y ], $class ; # 暗黙の return }sub Point ::distance { my ( $self , $from ) = @_ ; my ( $dx , $dy ) = ( $$self [ 0 ] - $$from [ 0 ], $$self [ 1 ] - $$from [ 1 ]); sqrt ( $dx * $dx + $dy * $dy ); }new()このクラスは、インスタンスを構築するために呼び出し、それらのインスタンスに対してを呼び出すことによって使用できますdistance。
my $p1 = Point -> new ( 3 , 4 ); my $p2 = Point -> new ( 0 , 0 ); print $p1 -> distance ( $p2 ); # 5 と出力されます多くの最新のPerlアプリケーションは、Mooseオブジェクトシステムを使用しています。Mooseは、メタオブジェクトプロトコルであるClass::MOPの上に構築されており、Mooseを使用するすべてのクラスに対して完全なイントロスペクション機能を提供します。そのため、シンプルなAPIを使用して、クラスの属性、親、子、メソッドなどについて問い合わせることができます。
ムースクラス:
ムースの役割:
MooseX::Declare [ 10 ]拡張機能を使用して記述されたクラスの例:
use MooseX::Declare ; class Point3D extends Point { has 'z' => ( isa => 'Num' , is => 'rw' ); クリア後 { $self- > z ( 0 ); } メソッドset_to ( Num $x , Num $y , Num $z ) { $self- > x ( $x ); $self- > y ( $y ); $self- > z ( $z ); } } これは、 Moose の例で説明されてPoint3Dいる別のクラスを拡張するクラスです。基底クラスに新しい属性を追加し、メソッドを再定義し、メソッドを拡張します。Pointzset_toclear
[…] 引用符のない文字列、ベアワード文字列として知られています […]