Perlリファレンスについてどのくらい知っていますか?Perlリファレンスに関するいくつかのチュートリアルを見たいと思うかもしれません。
クイックリファレンスチュートリアル
Perlの3つの基本的なデータ構造(スカラー、配列、ハッシュ)はすべて、単一のデータ値を保持するように設計されています。たとえば、私には一連の従業員がいます。
$employee_list[0] = "Bob";
$employee_list[1] = "Carol";
$employee_list[2] = "Ted";
$employee_list[3] = "Alice";
はい、私の配列には4つのデータがありますが、単純なPerlでは、各項目には1つの値(名)しか含まれていません。従業員の名前、給与、役職も必要な場合はどうすればよいですか?基本的なPerlデータ構造でそれを行う簡単な方法はありません。
参照は、Perl変数に複数のデータを格納できるようにする方法です。ボブの完全な従業員記録を見てみましょう。
$employee{FIRST} = "Bob";
$employee{LAST} = "Jones";
$employee{PAY} = "1400";
$employee{PHONE} = "1234";
では、どうすればそのすべての情報を絞り込め$employee_list[0]
ますか?
Perlでは、このハッシュ(主にそのハッシュが格納されているメモリ内の場所)への参照を取得できます。これを行うには、その前に円記号を付けます。%employee
$employee_list[0] = \%employee;
さて、その1つの$employee_list[0]
スロットに、ボブのすべての従業員情報を含むPerlハッシュへの参照があります。さて、問題はどうすればこの情報にアクセスできるかということです。
参照を解除することで、参照内の情報にアクセスできます。参照の前に正しい印章を置くことによってそれを行います:
$employee_reference = $employee_list[0];
%employee_hash = %$employee_reference;
print "Employee name is $employee_hash{FIRST} $employee_hash{LAST}\n";
最初に参照を取得し、次にそれを新しいに逆参照でき%employee_hash
ます。そうすれば、ハッシュにある情報を使用できます。それは大変な作業です。を見てください$employee_reference
。それで私がしているのは参照を取得することだけなので、それを逆参照することができます。そのステップを切り取って、私の間接参照を右から取ってみません$employee_list[0]
か?
%employee_hash = %{ $employee_list[0] };
print "Employee name is $employee_hash{FIRST} $employee_hash{LAST}\n";
参照の周りに中括弧を使用していることに注意してください。中括弧は、方程式を囲む括弧のようなものです。彼らはPerlに最初に何をすべきかを知らせます。
繰り返しになりますが、私は実際には何もしていません%employee_hash
。ハッシュを投げることができる場所なので、印刷することができます。ハッシュを逆参照して、特定のキーの値を1つのステップで取得してみませんか?さらに良い。単一のステップで:
print "Employee name is "
. ${ $employee_list[0] }{FIRST} . " "
. ${ $employee_list[0] }{LAST} . "\n";
ハッシュを逆参照$employee_list[0]
してそのハッシュを取得し、特定のキーの値をすべて同じステップで取得しています。の代わりにを使用していることに注意してください。$
%
ご覧のとおり、すぐに複雑になる可能性があります。ただし、Perlは、この非常に複雑な構造を表現するための優れた方法を提供します。
print "Employee name is "
. $employee_list[0]->{FIRST} . " "
. $employee_list[0]->{LAST} . "\n";
->
演算子が間接参照を取得します。
%employee_hash
また、参照するためだけに呼び出されるハッシュを作成するのも、一種のばかげています。Perlでは、匿名のハッシュと配列を参照できます。
$employee_list[0] = { LAST => "Jones", FIRST => "Bob",
SALARY => 1400, PHONE => "1234" }
中括弧は匿名ハッシュ用です。角括弧は匿名アレイ用です。それらは変数を参照しないため匿名ですが、単にハッシュまたは配列への参照です。
データ::ダンパー
ご想像のとおり、これらのデータ構造は非常に複雑になる可能性があります。たとえば、私は従業員の住所を追跡していますが、住所は通り、都市、州、および郵便番号で構成されています。時々、通りには複数の線があります。また、複数のアドレスがある場合はどうなりますか?ハッシュまたは配列の参照に別のハッシュまたは配列への参照を含めることができない理由はありません。
$employee_list[0]->{NAME}->{FIRST} = "Bob";
$employee_list[0]->{NAME}->{LAST} = "Jones";
$employee_list[0]->{ADDRESS}->[0]->{TYPE} = "Business";
$employee_list[0]->{ADDRESS}->[0]->{STREET}->[0] = "123 Mockingbird Lane";
$employee_list[0]->{ADDRESS}->[0]->{STREET}->[1] = "Tower 2";
$employee_list[0]->{ADDRESS}->[0]->{CITY} = "Beantown";
$employee_list[0]->{ADDRESS}->[0]->{STATE} = "MA";
ご覧のとおり、$employee_list[0]は従業員ハッシュへの参照を指しています。そのハッシュには、「NAME」、「ADDRESS」、およびデータで満たされたその他のキーがあります。このフィールドは、とNAME
の2つのキーを持つ別のハッシュへの参照です。このフィールドは、実際にはアドレスの配列への参照です。そして、これらの配列エントリのそれぞれは、ハッシュへの参照です。このデータ構造をデバッグしようとしているところを想像してみてください。FIRST
LAST
ADDRESS
Data :: Dumperは、最も複雑なデータ構造を解析して出力するモジュールです。
use Data::Dumper;
[...]
print "Employee Dump: " . Dumper \@employee . "\n";
これにより、employee配列内のすべての従業員の構造全体が出力されます。
何であるかわからない場合@{$value{$key}}
は、簡単にダンプを実行できます。
print Dumper $value{$key} . "\n";
プログラムのデコード
行を1つずつ見ていきましょう。
%Routings = ();
my $dbh = DBI->connect('dbi:ODBC:SQL')
or die "Couldn't open Databaxe: $DBI::errstr; stopped";
と呼ばれるハッシュを初期化%Routings
し、データベースへの接続を表すDBIオブジェクトを作成しました。connect
DBIクラスの一部としてPerlで定義されているサブルーチンです。すべてのクラスは、そのクラスによって作成されたオブジェクトを操作する一連のPerlサブルーチンで構成されています。これらのサブルーチンは、コンストラクターとメソッドに分けられます。コンストラクターは、オブジェクトを表す複雑なデータ構造への参照を作成します。メソッドは、そのオブジェクトを操作できるサブルーチンです。従業員の記録を想像してみてください。
$employee = Person::Employee->new;
$employee->first_name( "Bob" );
最初の行は、クラス$employee
からオブジェクトを作成します。Person::Employee
その$employee
オブジェクトは、実際には私の従業員情報を含むハッシュへの単なる参照です。したがって、私のサブルーチンnew
はコンストラクターです。
first_name
2行目は、従業員の名を設定できるというサブルーチンを使用しています。このサブルーチンは、メソッドまたはメンバー関数と呼ばれることもあります。
そこで、プログラムに戻って、データベース接続を表すオブジェクトを作成しました。必要に応じて、このオブジェクトの構造を少しよく理解するのに役立つ場合は、このオブジェクトData::Dumper
の構造を印刷するために使用できます。これはハッシュへの単なる参照です。
my $query= $dbh->prepare("SELECT Code, Setup, Process, ProcessID FROM ROUTING");
$query->execute() or die "Couldn't execute statement: $DBI::errstr; stopped";
次に、実行するSQLステートメントを準備します。準備してから実行します。実行は実際にデータベースに影響を与えるものです。prepare
myはデータベースハンドルのメソッドですが、オブジェクト$dbi
を作成したため、コンストラクターでもあることに注意してください。$query
そのオブジェクトを使用して$query
、実際にクエリを実行します。Data::Dumper
繰り返しますが、それを印刷するために使用することを恐れないでください。
while ( my ($Code, $setup, $process, $processid) = $query->fetchrow_array() ){
push ( @{ $Routings{$Code} }, [ $ProcessID, $Setup, $Process ] );
}
これを少し単純化しましょう:
while ( my @fetched_row = $query->fetchrow_array() ){
my ($Code, $setup, $process, $processid) = @fetched_row;
push ( @{ $Routings{$Code} }, [ $ProcessID, $Setup, $Process ] );
}
これfetchrow_array
は、クエリから1つの行を列の配列としてフェッチするサブルーチンです。このサブルーチンは、上記で作成したオブジェクトのメソッドです。$query
私がしているのは、データベースから各行をフェッチし、それを4つのPerlスカラー変数に入れることだけです。
最後の行は少し注意が必要です。%Routings
初期化したハッシュを覚えていますか?どうやら、このハッシュの各キーは値の配列への参照です。ハッシュは、上記でフェッチしたキーが付けられており、これは、、、および$Code
で構成される3つのメンバーの配列を指します。3行目を次のように書き直すことができます。$ProcesssID
$Setup
$Process
my @temp_array = ($ProcessID, $Setup, $Process);
my @temp_routing_array = @{ $Routings{Code} }; #Dereferencing the $Routing{$Code} array
push( @temp_routing_array, \@temp_array ); #Pushing a reference into my array
$Routing{$Code} = \@temp_routing_array; #Creating a reference again
は[ $ProcessID, $Setup, $Process ]
、匿名配列への参照を作成するだけです。これにより、の参照を作成してから自分のに@temp_array
プッシュする手間が省けます。@temp_array
@temp_routing_array
そして、私たちがそれに取り組んでいる間、あなたのコードにエラーがあります。$setup
、、、$process
およびをフェッチ$processid
していますが、(変数名の大文字と小文字を区別して)、、、およびを格納して$Setup
い$Process
ます$ProcessID
。
これで、foreachループと別のバグが発生します。の価値は$Code
何ですか?変数は上記のループ$Code
にのみ存在するため、値はありません。while
で変数を宣言するとmy
、コードのブロックを離れると、この変数の値は失われます。
このエラー、および上記のエラーは、プログラムの最上位にある場合に検出された可能性がuse strict;
ありuse warnings;
ます。
このループを見てみましょう:
foreach ( @{ $Routings{$Code} } ) {
my $ProcessCodeID = @$_[0];
my $SetupMins = @$_[1];
my $ProcessMins = @$_[2];
}
このforeach
ループは、$_
変数をループしていると想定する廃止されたスタイルを使用しています。それは紛らわしく、ほとんどの人はそれを使わないことを学びました。それを書き直してみましょう:
my @routing_code_ref_array = @{ $Routings{$Code} };
foreach my $routing_array_ref (@routing_code_ref_array) {
my @routing_array = @{ $routing_array_ref };
my $ProcessCodeID = $routing_array[0];
my $SetupMins = $routing_array[1];
my $ProcessMins = $routing_array[2];
}
$Routings{$Code}
これは配列への参照であることを忘れないでください。私の最初の行では、それを間接参照しています。foreach
元のコードでは、間接参照はループで行われました。配列参照であるだけでなく$Routings{$Code}
、その配列の各エントリは別の配列への参照でした。配列の配列です。
したがって、私の各エントリは、@routing_code_ref_array
もう一度逆参照する別の配列への参照です。今、私は各配列要素の値を取得し、それを通常のPerlスカラー変数に入れています。
もう十分!
長い説明で申し訳ありませんが、参照、クラス、メソッド、コンストラクター、オブジェクト、およびかなり高度なPerlトピックの全体に触れたコードがいくつかありました。私が指摘したいくつかのエラーと同様に。いくつかの標準的なPerlプラグマでキャッチされた可能性のあるエラー:use strict;
およびuse warnings;
。
あなたが奪うことができる何かがあるならば、それは次のとおりです:
@$foo{$bar}[4]
or@{ $foo{bar} }[4]
または(より正確に)${ $foo{bar} }[4]
または(より明確に)のようなもの$foo{bar}->[4]
は、より複雑なデータ構造への参照です。基本的なPerlデータ構造は、一度に1つのアイテムしか保持できません。他のデータ構造への参照を使用することにより、配列の配列またはハッシュの配列またはハッシュのハッシュまたは配列のハッシュ、さらにはハッシュの配列のハッシュの配列を使用できます。慌てずに、これらのことを裏返しに解析してみてください。特に複雑なデータ構造を複数行で処理できると、より簡単な場合があります。
- あなたが複雑な構造に遭遇するつもりなら、
Data::Dumper
あなたの友達です。これらの非常に複雑な構造の構造をすばやく明らかにし、プログラムの問題をデバッグするのに役立ちます。
strict
とをプログラムで使用warnings
します。これらは多くのプログラミングの失敗を拾います。私が言ったように、私はローカル変数のスコープと変数名の場合のタイプミスの両方に関連する2つを見つけました。変数名を標準化することも素晴らしいアイデアです。2つの方法は、キャメルケースとアンダースコアと小文字のみを使用する方法です。このように、あなたはそれが常に$foo_bar
そして決して$Foo_Bar
または$FooBar
またはではないことを知っています$fooBar
。古い標準は、最初の文字が小文字であるキャメルケースでした。新しい標準では、小文字とアンダースコアのみが使用されています。