7

私は次のように参照渡しを行っています:

use strict;
use warnings;

sub repl {
    local *line = \$_[0]; our $line;
    $line = "new value";
}

sub doRepl {
    my ($replFunc) = @_;
    my $foo = "old value";
    $replFunc->($foo);
    print $foo; # prints "new value";
}

doRepl(\&repl);

それを行うよりクリーンな方法はありますか?

関数参照を使用しているため、プロトタイプは機能しません (関数参照を使用するのには十分な理由があると信じてください)。

また、醜いので、$_[0]どこでも使用したくありません。repl

4

4 に答える 4

9

Data :: Aliasを見たことがありますか?クリーンな構文で字句スコープのエイリアスを作成できます。

これを使用して、次のような参照渡しのセマンティクスを作成できます。

use strict;
use warnings;

use Data::Alias;

sub foo {
    alias my ($arg) = @_;
    $arg++;
}

my $count = 0;

foo($count);

print "$count\n";

出力は1、であり、呼び出しがfoo引数を変更したことを示します。

于 2010-03-17T18:22:45.477 に答える
3

これを行うにはいくつかの方法があります。スカラー参照を明示的に渡す$fooか、Perlの組み込みの参照セマンティクスによるパスを利用します。

明示的な参照:

my $foo = "old value";
doRepl( \&repl, \$foo );
print $foo; # prints "new value";

sub repl {
    my $line = shift;
    $$line = "new value";
}

sub doRepl {
    my ($replFunc, $foo) = @_;
    $replFunc->($foo);
}

参照渡し:

my $foo = "old value";
doRepl( \&repl, $foo );
print $foo; # prints "new value";

sub repl {
    $_[0] = "new value";
}

sub doRepl {
    my $replFunc = shift;
    $replFunc->(@_);
}

参照によるより手の込んだパスでさえ:

my $foo = "old value";
doRepl( \&repl, $foo );
print $foo; # prints "new value";

sub repl {
    $_[0] = "new value";
}

sub doRepl {
    my $replFunc = shift;
    &$replFunc;
}

最初のものは、通常のperlハードリファレンスを使用して仕事をします。

refによる最初のパスメソッドは、Perlがすべての関数に引数を参照として渡すという事実を使用します。の要素は@_、実際には、サブルーチンが呼び出されたときの引数リストの値のエイリアスです。を変更$_[0]することによりfoo()、実際には最初の引数をに変更しますfoo()

&refメソッドによる2番目のパスは、 sigilで呼び出され、parensがないsub@_がその呼び出し元の配列を取得するという事実を使用します。それ以外は同じです。

更新:あなたが避けたいと思っていることに気づきました$_[0]。必要に応じて、replでこれを行うことができます。

sub repl {
    for my $line( $_[0] ) {
        $line = 'new value';
    }
}
于 2010-03-17T18:20:34.200 に答える
3

 

sub repl {
    my $line = \$_[0];     # or: my $line = \shift
    $$line = "new value";
}
于 2010-03-17T18:34:58.760 に答える
0

localこの場合、エイリアスを作成するために使用しても問題はないと思います。

動的スコープはもちろん強力な機能ですが、副作用を認識している限り (スコープから呼び出された関数で新しい値が表示され、同じ名前のレキシカルがスコープ内にある場合、ローカライズできません。 ...) それなら、すでにあふれている Perl ツールボックスに便利な追加機能です。

Perl ドキュメントの警告の主な理由は、local人々が不注意で perl4 の代わりにそれを使用しないようにすることmyと、perl4 からの移行を容易にすることです。しかし、確かにlocal便利な場合があり、これはその 1 つです。

を使用forしてエイリアスを作成することもオプションですがlocal、意図が明確な明示的な構文が見つかりました。パフォーマンスが懸念される場合は、少し高速です。

于 2010-03-17T20:54:57.283 に答える