• ベストアンサー

Perlでのselfの書き方

お世話になっています。 今他人が作ったPerlのプログラムを見ているのですが、 その中で、 パラメータを受け取る部分が、、、 sub hogehoge { my $self = shift; my ($one, $two) = @_; .. bra bra bra } と言う感じになっています。 またPerl初心者ですが、私の調べたところでは、 この二つの行は同等の意味なので、 sub hogehoge { my ($self, $one, $two) = @_; ... bra bra bra } と一行でかけてしまうと思うのですが、 $selfと$one, $twoを2行に分けている理由とか あるのでしょうか。 $selfだけ2行目の方法ではかけないとか? それともただ単に、 my $self = shift; と1行目に書くのがならわしだからでしょうか。 詳しい方が居ましたらよろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

まず最初に答えを書いてしまうと「どちらの形式でも動作するが, 論理的な意味を考えれば前者の方がイメージにマッチする」ということになるかと. メソッドを $obj->method($arg1, $args); のように起動した場合, メソッドの最初では @_ = ($obj, $arg1, $arg2) の関係にあります. しかし, 意味を考えれば @_ = ($arg1, $arg2) となっている方が自然であり, そのようにするにはまず最初に my $self = shift; のように shift を行う必要があります.

sforest
質問者

お礼

ありがとうございました! もやもやがとれました!

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (2)

  • zxcv0000
  • ベストアンサー率56% (111/196)
回答No.3

No.1さん、No.2さんの回答もそのとおりですが、もうひとつ。 Perl のメソッドでは、$_[0] はオブジェクトと決まっています。 これを格納する変数名を $self に統一するのはソースを見易くする効果があります。 加えて、先頭に my $self = shift; と書く様に統一すれば、さらに見易くなります。 # 動かないソースコードを睨んでいる時、$self の格納が正しくできている事が一目で判るのは、重大なメリットです。

sforest
質問者

お礼

最初一行のほうがシンプルで いいのになんでだろう って思っていたのですが、 たしかにいわれてみればそのとおりですね ありがとうございました!

全文を見る
すると、全ての回答が全文表示されます。
回答No.2

hogehogeの中でその後@_を使うのでなければ一緒だと思います。

sforest
質問者

お礼

ああなるほど @_そのままパラメータでループさせたい場合などは 先に、selfはとってしまったほうが便利なのですね! ありがとうございました

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • perlのクラスについて

    perlでクラスを作成しています。その際、コンストラクタnewで無名配列を定義して、funcメソッドで、この無名配列に値をいれるにはどうすればよいでしょうか? sub new { my $class = shift; my $self->array = []; bless($self, $class); return $self; } sub func { my $self = shift; $self->arrayに配列のデータを入れる。 }

    • ベストアンサー
    • Perl
  • Perlで特定行から特定行までを抜き出したい

    皆さんのお知恵をお貸し頂ければ幸いです。 Perlで以下のようなことをしたいと考えています。 例えば、次のようなテキストファイルがあったとします。 example.log ================================== aaaa hogehoge test okok perl script ================================== 上記ファイルを読み込んで、「hogehoge」から「perl」の間に挟まれた行だけ抜き出したいのです。 イメージとしては、読み込んだファイルを配列に入れて、一行づつ読ませ、キーワード「hogehoge」が現れたらそこでフラグを立て、それ以降の行を表示し、キーワード「perl」が現れた時点で表示を止めるという処理になるのかな?と思っています。 このような場合、どういう風にすればいいのでしょうか? 恐れ入りますが、ご教授頂ければ幸いです。 それでは、どうぞよろしくお願い致します。

    • ベストアンサー
    • Perl
  • perlでテキスト複数行を関連付けしながら変数に代入していく方法を教えてください。

    下記の様なグループ分けされたテキストデータを読み込んで ■テキストデータ group 1 list one match hogehoge1 hogehoge2 set pogepoge1 pogepoge2 group 2 list two match hogehoge1 hogehoge2 set pogepoge1 pogepoge2 ・・・・・・・・ この様に、複数の group で、中にはいくつかの list が存在し、 その中に match/set でコメントが書かれていまして これらを、『group,list,match/set,コメント』 の様にカンマ区切りにしたいです。 ■perl 実行後 group 1,list one,match,hogehoge1 group 1,list one,match,hogehoge2 group 1,list one,set,pogepoge1 group 1,list one,set,pogepoge2 group 2,list two,match,hogehoge1 group 2,list two,match,hogehoge2 group 2,list two,set,pogepoge1 group 2,list two,set,pogepoge2 なお、group の中には list がない場合もあります。。 # この場合はカンマ間を空白にしたい group 1,,match,hogehoge1 group 名は一意な名前がついていますが、list 名やコメントは 同じ情報が入っている場合があります。 この様に情報を関連付けながら変数に代入していきたいと思います。 どんなことでも、参考になりそうなことがありましたら是非是非、ご紹介ください。 宜しくお願い致します。

  • use baseしたpackageのローカル変数の書き換え

    packageを継承した場合、 継承先(以下のMyPkg)で継承もと(MyBase)のローカル変数($localValue)を直接書き換える方法はありませんか? package MyBase; my $localValue; sub doBase{ my $self=shift; $localValue ={ 'hanako'=>{'id'=>1, 'pref'=>'tokyo'} }; } sub getPref { my $self=shift; my $name=shift; $localValue->{$name}{'pref'}; } package MyPkg; use base qw(MyBase); sub new{ my $class=shift; my $self={}; bless $self, $class; return $self; } sub doAnything { # この中でMyBaseの$localValueを直接書き換えたい $localValue ={ 'taro'=>{'id'=>2, 'pref'=>'osaka'} }; } ------main:: my $pkg=new MyPkg; $pkg->doSomething; print $pkg->getPref('hanako'); $pkg->doAnything; print $pkg->getPref('taro'); ---------- 以下のような感じでmyBaseの中に$localValueを返すサブルーチンを作っておけば、 print $pkg->localValue->{'hanako'}{'pref'}; などと取得は出来ますが、 $pkg->localValue->{'hanako'}{'pref'}='kyoto'; のような代入は無理みたいでした。 package MyBase; my $localValue; sub localValue{ my $self=shift; $localValue; } doBaseのようなサブルーチン経由で書き換えていますが、 use baseしていても、やはりそうしないとダメでしょうか。 Windows、ActivePerl、perl 5.10.0 Linux、Perl5.8

  • [perl]メソッドの引数で受け取った配列データを直接編集したい

    現在、業務でperlプログラムを書いてます。 perlを初めて2か月、プログラムは ほぼ初です。 よろしくおねがいします。 例えば以下のようなコードで、「sub_func」というメソッド内で「main」メソッド内の配列データを直接編集したいのですが、うまくいきません。 これは、引数で渡しているのは配列の「ポインタ」ではなく「リファレンス」であるため、「sub_func」というメソッド内で、新たに「array_ref」という配列の実態を作成してしまっているのだと認識しています。 そのため、「main」メソッドに戻ったタイミングではデータは元に戻ってしまうのだと思っています。 sub sub_func {    my ($self, $array_ref) = @_ ;    $array_ref = [4,5,6];   # returnはせずに、引数で指定したデータに格納したい } sub main {    my ($self) = @_ ;    # メソッドに渡すデータ    my $data = {       array => [1,2,3],    };    my $data2 = [1,2,3];    my @data3 = (1,2,3);    # メソッドの中で、$data->{array}を [4,5,6] に変えたいが・・・    $self->sub_func( $data->{array} );    $self->sub_func( $data2 );    $self->sub_func( \@data3 );    # この時点で、どれも [1,2,3] のまま } 私の認識は間違っているのでしょうか?? また、どのようにすれば配列の要素を別のメソッド内で編集できるのでしょうか?? 御助言をお願いします。

    • ベストアンサー
    • Perl
  • perlのプログラミングについて

    perlのプログラミングについて詳しい解説をお願いいたします。 sub list_reverce{ my $old=shift; my&new=undef; while (my $cur=$old){ $old=$old‐>[NEXT]; $cur‐>[NEXT]=$new; } return $new } 全くの初心者です。連結リストに対してのreverseなのですが、わかりません。 ご回答お願いいたします。

    • ベストアンサー
    • Perl
  • Perl 強制終了の回避について

    Attempt to free unreferenced scalar とは? http://oshiete1.goo.ne.jp/qa4237453.html の続きです。 とりあえず、下に現状で分かる最小限の再現性があるスクリプトを 書いておきます。 print &opentmpl("body"); print &opentmpl('footer'); # これがない場合はエラーにならない sub opentmpl { my $fn = shift; my $VAR = shift || {}; my $file = &{$fn}(); &regex(\$file, $VAR, '__([A-Z_\d]+?(\[\d+?\])?)__', ['$VAR->{"%s"}', '$1']); &regex(\$file, $VAR, '&{(.+?)}&', ['%s', '$1']); return $file; return undef; } sub regex { my $str = shift; my $VAR = shift; my $pattern = shift; my $replace = shift; $$str =~ s/((([^\n]*?)$pattern(?=.*))+(\n?))/&func($1, $VAR, $pattern, @$replace)/egs; return; } sub func { my $str = shift; my $VAR = shift; my $pattern = shift; my $buf = shift; $str =~ s/$pattern/$@ = ''; $_ = eval(sprintf($buf, map { eval($_); } @_)); $@ ? $@ : $_/egs; if($str =~ /^\s*\n?$/s) { return; } return $str; } sub body { print "Content-type: text/plain; charset=shift_jis\n\n"; return <<'HTML'; &{ return &opentmpl('table', {'TEST' => 'test'}); }& HTML } sub table { return <<'HTML'; __TEST__ HTML } sub footer { return <<'HTML'; test HTML } 調べてみた限りではActivePerl for Win32以外のPerlでも同様のよう です。 (Linux上でも同様のようです) 5.8.8ではエラーになりますが、5.10.xではエラーにならないようです。 (同じ環境において5.8.8では再現し、5.10.0にバージョンアップすると 再現しなくなり、再度5.8.8にバージョンダウンすると再現します) 本番機の環境が5.8.8で勝手にバージョンアップなどができないため、 5.8.8で正常に動作するようにするにはどうしたらよいでしょうか。 結構、無駄も多いと思いますので全く同じ動作をしながらより効率の いい書き方ができたらいいなと思います。 (なお、実際には使用しているけど上記では使用していない部分が 含まれていてその部分がない場合もエラーにならないようです)

    • ベストアンサー
    • Perl
  • perlの構文でわからない部分があるので教えて下さい。

    こんにちわ。パールの文で解らない部分があり困って居ります。$class->SUPER::new();ここの箇所なのですが、$classはどこから来たものなのかがわからなくて、メソッドの起動なのかとも思ったのですが、本も調べてみたのですがはっきりしません。お解りの方、どうか教えて下さい。よろしくお願いします。 package CGIBook::UserTracker; push @ISA,"HTML::Parser"; use strict; use URI; use HTML::Parser; 1; sub new{my($class,$path)=@_; my$id; if($ENV{PATH_INFO}and $ENV{PATH_INFO}=~ s|^/\.([a-z0-9_.-]*)/|/|i){$id=$1;} my$self=$class->SUPER::new(); $self->{user_id}=$id;$self->{base_path}=defined($path)?$path:""; return$self;}

    • ベストアンサー
    • Perl
  • Perl、オブジェクト指向での初期設定ファイルについて。

    Perl、オブジェクト指向での初期設定ファイルについて。 最近、Perlでのオブジェクト指向を勉強中です。 今までのプログラムをオブジェクト指向に書き直そうと思っています。 クラスを作成して呼び出す程度までは理解できたのですが、 今まで、サーバの絶対パスや、データベースの名称などを、 config.pl というファイルを作って、グローバル変数で宣言していました。 例 $local_parh = "/virtual/xxx/bbb/public_html"; $dbname = "testdb"; $dbuser = "username"; でも、オブジェクト指向では、グローバル変数を使わないようにするということで、 このあたりをふつうはどんなふうに作成するのかとおもったのですが、 なかなか検索しても見つかりません。(検索の仕方が悪いのかもしれませんが) 今思いつく方法は、config.pm などを作って -------------------------------------------------- package Config; sub new{ my $class = shift; my $self= { local_path => '/virtual/aaa/bbb/public_html', dbname => 'testdb', dbuser => 'username' }; return bless ($self,$class); } sub get_local_path { my ($self, $name) = @_; return $self->{'local_path'}; } -------------------------------------------------- use Config; $obj=new Config(); $local_path = $obj->get_local_path(); -------------------------------------------------- とするような感じなのですが、なんだかスマートじゃない気がするので 普通ははどんなふうに書くのか教えてもらえますか?

    • ベストアンサー
    • Perl
  • Perl 禁止語句

    テキストの中に禁止語句一覧があります。 それと一致した場合、エラーを返すのですが、 現在のコードですと、 完全一致で、これを部分一致にする 方法を教えてください。 またコードの指摘があればよろしくお願いいたします! ◆ngword.txt◆ あい いう うえ えお ・ ・ ・ 1000行ほど(もっとあるかもしれません) ◆test.pl◆「UTF-8」 #/usr/bin/perl use Encode; my $Name = "え"; $Name = encode('cp932', decode('UTF-8', $Name)); open my $fh, '<', 'ngword.txt'; chomp(@ngword = <$fh>); if(&ban($Name, \@ngword)) { print "error\n"; } sub ban { my $body = shift; my $word = shift; $body =~ s/(\x0d\x0a|\x0a|\x0d|\n|\s|\x81\x41|\xff)//g; return map { $body =~ /$_/m } @$word; }

    • ベストアンサー
    • Perl