Perlや他の言語の共通のイディオムは、名前空間へのインタフェースを効果的に提供する「神」オブジェクトを渡すことです。これにより、すべての関数をネームスペースにインポートするのではなく、メソッドを呼び出すことができます。これらの各ネームスペースは、異なるランタイムデータ(オブジェクトのインスタンス)でカスタマイズすることもできます。
オブジェクトでメソッドを呼び出す構文が嫌いなら、探しているものがJavascriptのwith
ブロックに似ているように思えます。
use warnings;
use strict;
use Carp();
sub with ($&) {
my ($obj, $code) = @_;
my $auto = (caller).'::AUTOLOAD';
no strict 'refs';
local *$auto = sub {
my ($name) = $$auto =~ /([^:]+)$/;
my $method = $obj->can($name)
|| $obj->can(lcfirst $name)
or Carp::croak "no method '$name' on '$obj' in with block";
unshift @_, $obj;
goto &$method
};
$code->()
}
モックオブジェクトを考える:
{package Obj;
sub new {bless []}
sub log {shift; say "logging @_"}
sub model {shift; say "setting model to @_"}
}
は、あなたがそれから書くことができます:
my $c = Obj->new;
with $c => sub {
model('DBIC::Table');
Log('hello world'); # ucfirst
&log('hello again'); # or with a & since 'log' is a builtin
};
Perlがこれを行い天然の構造を持っていませんが、それはものを作るためのツールを提供してい
次のうちどれが印刷されますか:
setting model to DBIC::Table
logging hello world
logging hello again
楽しんでください。すでに定義されているサブルーチンの名前または名前は、with
ブロックでオーバーライドされません。名前のucfirst
バージョンを使用するか、それらのインスタンスでメソッドを呼び出すことができます。 with
ブロック内のすべての新しいサブルーチンは、コンパイル時にその名前がわからないため、Log('hello')
という括弧で呼び出され、Log 'hello'
ではなく、呼び出される必要があります。
私はRakudoの方法を呼び出す方が好きですが、構文に関する質問ではありませんでした... – xenoterracide
@xenoterracide =>なぜあなたは触媒に '$ c-> log-> warn ...) '(' log(warn => ...) 'の代わりに' 'これは構文上の違いです。その理由は、それが触媒の思想家の思想が最も良かったからです。だから、私はあなたに望み通りに書く方法を与えました(この場合、 '' Log() - > warn(...) ''これは触媒の '' log'メソッドの仕組みなので)、答えはあなたが期待していましたか? –
は、コンテキストオブジェクトを通してすべてが行われる理由についてさらに詳しく質問しています。通常は、外部のものにもアクセスされます。構文の正確な理由は、コンテキストオブジェクトを介している理由よりもはっきりしています。言うまでもなく、単にログapiを直接使用します。 – xenoterracide