慎重に使用することが重要な例をいくつか示し@_
ます。
1. Hash-y 引数
キーと値のペアのリストを取得できる関数を作成したい場合がありますが、1 つが最も一般的な用途であり、キーを必要とせずに利用できるようにしたい場合があります。例えば
sub get_temp {
my $location = @_ % 2 ? shift : undef;
my %options = @_;
$location ||= $options{location};
...
}
したがって、奇数の引数で関数を呼び出す場合、最初は場所です。これによりget_temp('Chicago')
、 またはget_temp('New York', unit => 'C')
または さえも可能になりますget_temp( unit => 'K', location => 'Nome, Ak')
。これは、ユーザーにとってより便利な API かもしれません。奇数引数をシフトすることにより、偶数@_
リストになり、ハッシュに割り当てることができます。
2.発送
メソッドを名前でディスパッチできるようにしたいクラスがあるとしましょう (おそらく AUTOLOAD が便利かもしれません。手でロールします)。おそらく、これは引数がメソッドであるコマンド ライン スクリプトです。この場合、「クリーン」と「ダーティ」の 2 つのディスパッチ メソッドを定義します。フラグを指定して呼び出すと-c
、クリーンなフラグが取得されます。これらのメソッドは、名前でメソッドを見つけて呼び出します。違いはやり方です。汚れたものはスタック トレースに残ります。クリーンなものはより包丁である必要がありますが、スタック トレースに含まれずにディスパッチされます。death
その痕跡を私たちに与えるメソッドを作ります。
#!/usr/bin/env perl
use strict;
use warnings;
package Unusual;
use Carp;
sub new {
my $class = shift;
return bless { @_ }, $class;
}
sub dispatch_dirty {
my $self = shift;
my $name = shift;
my $method = $self->can($name) or confess "No method named $name";
$self->$method(@_);
}
sub dispatch_clean {
my $self = shift;
my $name = shift;
my $method = $self->can($name) or confess "No method named $name";
unshift @_, $self;
goto $method;
}
sub death {
my ($self, $message) = @_;
$message ||= 'died';
confess "$self->{name}: $message";
}
package main;
use Getopt::Long;
GetOptions
'clean' => \my $clean,
'name=s' => \(my $name = 'Robot');
my $obj = Unusual->new(name => $name);
if ($clean) {
$obj->dispatch_clean(@ARGV);
} else {
$obj->dispatch_dirty(@ARGV);
}
だから今./test.pl
、死のメソッドを呼び出すために呼び出すと
$ ./test.pl death Goodbye
Robot: Goodbye at ./test.pl line 32
Unusual::death('Unusual=HASH(0xa0f7188)', 'Goodbye') called at ./test.pl line 19
Unusual::dispatch_dirty('Unusual=HASH(0xa0f7188)', 'death', 'Goodbye') called at ./test.pl line 46
dispatch_dirty
しかし、トレースでわかります。代わりに呼び出す場合./test.pl -c
は、クリーンなディスパッチャーを使用して取得します
$ ./test.pl -c death Adios
Robot: Adios at ./test.pl line 33
Unusual::death('Unusual=HASH(0x9427188)', 'Adios') called at ./test.pl line 44
ここで重要なのはgoto
(邪悪な goto ではなく) サブルーチン参照を取得し、現在の を使用して実行をその参照に即座に切り替えること@_
です。これがunshift @_, $self
、呼び出し元が新しいメソッドの準備ができるようにする必要がある理由です。