0

次のコードがあります。大きな値を切り捨てるために書きました。

   sub truncate_large_email_tag
    {
      my($email_tag) = @_;
      my $size = length($email_tag);

    if ($size>5000) { 
        my $fragment = substr($email_tag,0,5000);
        $email_tag = $fragment;
        #log_it( "\n\Truncated Large Email tags\n\n") if $TRACE;
        }

そして、別のサブルーチンの呼び出しを使用してこのサブルーチンを呼び出しています

  sub do_something
   {
  #some code here # CFG_PASS is a hash

        $EMAIL{$tag}=$CFG_PASS{$typ}{$tag}{$where . '_DEFAULTS'}; #Email        
        #tag initialized here
        truncate_large_email_tag($EMAIL{$tag});
        }

しかし、チェックすると、 $EMAIL{$tag} はまだ切り捨てられていない値を指しています。私は何か間違ったことをしていますか?

4

3 に答える 3

6

Perl は常に参照渡しです。問題は、パラメーターを変更したのではなく、関数で作成し、引数をコピーした変数 ( my ($email_tag) = @_;) を変更したことです。

変化する

my $fragment = substr($email_tag, 0, 5000);
$email_tag = $fragment;

my $fragment = substr($email_tag, 0, 5000);
$_[0] = $fragment;

また

$_[0] = substr($email_tag, 0, 5000);

また

$_[0] = substr($_[0], 0, 5000);

また

substr($_[0], 5000) = '';

だからあなたはで終わる

sub truncate_inplace {
    substr($_[0], $_[1]) = ''
        if length($_[0]) > $_[1];
}

truncate_inplace($EMAIL{$tag}, 5000);

しかし、なぜ使用しないのですか

sub truncate {
    my ($s, $max_len) = @_
    return length($s) > $max_len ? substr($s, 0, $max_len) : $s;
}

$EMAIL{$tag} = truncate($EMAIL{$tag}, 5000);
于 2013-09-07T17:46:40.243 に答える
2

あなたが推測したように、あなたは$EMAIL{$tag}値渡しをしているので、変更はサブ終了後に破棄され、オリジナルは変更されません。やりたいことを実行するには、2 つの方法があります。

方法 1:

truncate_large_email_tag(\$EMAIL{$tag});

これにより、参照が$EMAIL{$tag}サブルーチンに渡されます。サブ内では、作業を行うために逆参照する必要があります。

my ( $email_tag_ref ) = @_;
my $email_tag = $$email_tag_ref;

これは次のように省略できます。

my $email_tag = ${ $_[0] };

方法 2:

@_が特別であり、呼び出しパラメーターをエイリアスするという事実を利用します。

$_[0] = substr($email_tag,0,5000);

に直接割り当てること$_[0]で、元のパラメーターを変更します。

個人的には、より明示的であるため、方法 1 を好みます。

于 2013-09-07T17:51:14.477 に答える
1

perl では、スカラー引数は参照によって自動的に渡されます。それがここにあるものです。ハッシュ全体を渡そうとしているわけではありません。その中の値の 1 つだけを変更しようとしています。

次のように に代入することで、サブルーチン呼び出しの引数を変更できます@_

sub truncate_large_email_tag
{
    my($email_tag) = @_;
    my $size = length($email_tag);

    if ($size>5000) { 
        my $fragment = substr($email_tag,0,5000);
        $email_tag = $fragment;
        #log_it( "\n\Truncated Large Email tags\n\n") if $TRACE;
    }

    $_[0] = $email_tag;  # modify argument in the caller
}

とはいえ、通常は明示的な参照を送信する方が明確です。これを行うには、呼び出し時に引数の前にバックスラッシュを置き、$呼び出し先で逆参照する追加を使用します。

sub truncate_large_email_tag
{
    my ($email_tag_ref) = @_;
    my $size = length($email_tag);

    if ($size>5000) { 
        my $fragment = substr($email_tag,0,5000);
        $$email_tag_ref = $fragment;
        #log_it( "\n\Truncated Large Email tags\n\n") if $TRACE;
    }
}

そして、あなたがそれを呼び出すとき:

truncate_large_email_tag(\$EMAIL{$tag})
于 2013-09-07T17:47:46.467 に答える