4

タイスカラーを使用して、コードベースにいくつかの機能を追加しようとしています。

スカラーを返すように指定された関数があります。これらのスカラーを返す前に結合することでシステムにいくつかの機能を追加できると思いましたが、戻りの直前にFETCHメソッドが呼び出され、結合されていないスカラーが返されるようです。

これを回避する方法はありますか?

可能な限り、サブルーチンのインターフェース(スカラーを返す)をそのまま維持したいと思います。

use strict;
use warnings;
main();

sub GetThing{
    my $thing;
    tie $thing, 'mything', @_;
    return $thing;
}

sub main {
    my %m;
    $m{pre} = GetThing('Fred');
    print "1\n";
    print $m{pre};
    print "2\n";
    print $m{pre};
    print "3\n";
}


package mything;
require Tie::Scalar;

my @ISA = qw(Tie::StdScalar);

sub TIESCALAR {
    my $class  = shift;
    bless {
        name    => shift || 'noname',
    }, $class;
}

sub FETCH {
    my $self = shift;
    print "ACCESS ALERT!\n";
    return "    NAME: '$self->{name}'\n";
}

必要な出力:

1
ACCESS ALERT!
    NAME: 'Fred'
2
ACCESS ALERT!
    NAME: 'Fred'
3

参照を返し、アクセスごとに逆参照することで目的の出力を取得できますが、それによって確立されたインターフェイスが台無しになり、ユーザーが混乱しやすくなります。

-バック

4

4 に答える 4

4

DVKが言ったように、tieはコンテナーに適用されるため、戻りには役立ちません。

そのためには、オーバーロードを使用します。例(すべての可能なオーバーロード操作が提供されているわけではありません。http: //perldoc.perl.org/overload.html#Minimal-set-of-overloaded-operationsを参照してください):

use strict;
use warnings;
main();

sub GetThing{
    my $thing;
    $thing = "mything"->new(@_);
    return $thing;
}

sub main {
    my %m;
    $m{pre} = GetThing('Fred');
    print "1\n";
    print $m{pre};
    print "2\n";
    print $m{pre};
    print "3\n";
}


package mything;
use overload 'fallback' => 1, '""' => 'FETCH';

sub new {
    my $class = shift;
    bless {
        name    => shift || 'noname',
    }, $class;
}

sub FETCH {
    my $self = shift;
    print "ACCESS ALERT!\n";
    return "    NAME: '$self->{name}'\n";
}
于 2010-07-29T03:04:58.863 に答える
3

他の回答で述べたように、tieは値ではなくコンテナに適用されるため、結合された変数を別の変数に割り当てて、結合されたプロパティを保持する方法はありません。

GetThing割り当てが終了したため、コンテナをルーチンに渡す必要があります。これは、次のように参照することで実行できます。

use strict;
use warnings;
main();

sub GetThing{
    tie ${$_[1]}, 'mything', $_[0];
}

sub main {
    my %m;
    GetThing('Fred' => \$m{pre});
    print "1\n";
    print $m{pre};
    print "2\n";
    print $m{pre};
    print "3\n";
}


package mything;
require Tie::Scalar;

my @ISA = qw(Tie::StdScalar);

sub TIESCALAR {
    my $class  = shift;
    bless {
        name    => shift || 'noname',
    }, $class;
}

sub FETCH {
    my $self = shift;
    print "ACCESS ALERT!\n";
    return "    NAME: '$self->{name}'\n";
}

これにより、正しい出力が生成されます。

ただし、割り当てを保持する場合は、値に適用されるオーバーロードを使用する必要があります(実際にはオブジェクトに適用されますが、それ自体は値です)。意図した目的の詳細がなければ、完全な答えを出すことは困難ですが、これはあなたが述べた要件を満たします。

use strict;
use warnings;
main();

sub GetThing{
    return mything->new( shift );
}

sub main {
    my %m;
    $m{pre} = GetThing('Fred');
    print "1\n";
    print $m{pre};
    print "2\n";
    print $m{pre};
    print "3\n";
}


package mything;

sub new {
    my $class  = shift;
    bless {
        name    => shift || 'noname',
    }, $class;
}

use overload '""' => sub {   # '""' means to overload stringification
    my $self = shift;
    print "ACCESS ALERT!\n";
    return "    NAME: '$self->{name}'\n";
};

タイとオーバーロードの両方が複雑になる可能性があるため、不明な点がある場合は、すべてのドキュメントをお読みください。

于 2010-07-29T22:34:31.670 に答える
2

まず、あなたが提案していることを行う正確な方法は技術的に不可能に思えます:

  1. 結び付けられた変数には、変数の値ではなく、変数自体に結び付けられた結びつきがあります。

  2. Perlでは、サブルーチンの戻り値は値によって返されます。つまり、渡された値を取得してreturnアクセスし(この場合、タイ変数にアクセスFETCHしてプロセスを呼び出します)、その値をコピーします。つまり、呼び出し元が取得するのはスカラーVALUEであり、スカラー変数(タイドまたはアンタイド)ではありません。

要するに、あなたの混乱は、変数(プログラムのシンボルテーブル内の場所)とそれらの変数に格納されている値を混ぜ合わせることから生じているようです。


第二に、あなたは自分が何を達成しようとしているのかはっきりしていなかったので、あなたが望むものを達成する方法を提案するのは難しいです。しかし、あなたの説明に基づいて、サブルーチンの戻り時に何らかのメソッドを呼び出したい(おそらくそれを戻り値に渡す)と仮定すると、それを行うことができます。

そのためには、ファンシーな人々がアスペクトプログラミングと呼ぶものを採用する必要があります。Perlでそれを行うための政治的(および技術的)に正しい方法は、Mooseを使用することです。

ただし、基本的に元のメソッドをラッパーメソッドに置き換えることでDIYできます。

MooseとDIYの両方のアプローチの正確な仕組みは、次のSOの質問に対する最初の2つの回答に示されているので、ここではコピー/貼り付けしません。気にしないでください。

ダックタイピング言語での静的タイピングの側面のシミュレーション

于 2010-07-29T02:46:05.237 に答える
0

冒険心があれば、Scalar :: Deferモジュールを使用することもできます。このモジュールは、スカラー変数の汎用メカニズムを提供して、1回またはアクセスごとに値を遅延計算します。

于 2010-07-30T19:05:29.147 に答える