Perlコーディング初心者質問スレ Part 60at PHP
Perlコーディング初心者質問スレ Part 60 - 暇つぶし2ch250:nobodyさん
09/11/19 15:05:03 pgc2wImK
useでモジュールをロードできなかった場合に対処するコードを書いています。
eval "use Hoge::Hoge"; if ($@) { use Hoge::Hoge2; }

ある程度うまくいくのですが、失敗する場合もあり、原因がわからずにいます。
まったく同じ内容でpackage名だけが違うモジュールでテストしてみると・・・
(内容は$nameの定義とエクスポートだけ)
Hoge/Hoge.pm -> package Hoge::Hoge;
Fuga/Hoge.pm -> package Fuga::Hoge;

[1] eval "use Hoge::Hoge"; #=>存在するので読み込まれる
[2] eval "use Fuga::Hoge"; #=>存在するのに$@がセットされる($@は空の様子)
※[1]と[2]は別々にテストしています。

[2]のエラーメッセージは
Global symbol "$name" requires explicit package name at ...
use strictをはずして警告を見てみると、
$nameを参照しようとしたときに次のメッセージが出ます。
Name "main::name" used only once: possible typo at ...

[2]の場合も通常にuseすると問題ありませんし、次も成功します。
BEGIN {
 eval { require Fuga::Hoge; Fuga::Hoge->import(); }; if ($@) { (略) }
}

[2]だけ失敗してるいまいち理由がわからないんですが、
どういう状況か見当つきますか?

251:nobodyさん
09/11/19 15:09:31
もうすこしちゃんとソースをさらしてもらわないと説明だけでは
何をしてるのかわからん。

252:250
09/11/19 15:17:07 pgc2wImK
す、すみません。[2]のモジュールのソースは以下です。
package Fuga::Hoge;
our @EXPORT = qw($name);
use base qw(Exporter);
$name = 'myname';
1;

[1]はpackage名だけが違って、それぞれのパスに配置しています。
package Hoge::Fuga;

[1]は
eval "use Hoge::Fuga";
が評価されて$nameをimportできるのに、[2]だけ>>250の警告が出る状況です。
違いがわからないのと、メッセージの意味がじゅうぶん理解できなくて・・・

253:250
09/11/19 16:26:33
しばらく試しているのですが、どうも通常のuseと、evalした場合とでは
細かい違いがいろいろあるみたいです。
例えばモジュールでget_nameというサブルーチンをエクスポートしているとき、
通常のuseですと
my $name = get_name;
でOKですが、evalではエラーになったりするみたいです。
my $name = get_name(); #カッコがないとエラー

質問させてもらった件も、今ひとつつかみどころがない感じなので、
当面は安定を確認しているBEGINブロック内に記述する方法をとることにして、
尚、ドキュメントをあたってみたいと思います。

>>251さん、ありがとうございました。

254:nobodyさん
09/11/19 16:40:34
見た感じ読み込まれるモジュールの方は問題なさげなので
[1]とか[2]とか言ってる読み込み側のプログラムもきっちり
さらしてもらわないとわからんな。

BEGINブロックをつかわないでuseをeval "use ~" に置き換えると
読み込まれるにタイミングが変わるのでuse strictのコンパイル時
チェックに間に合わないというのはよくある話なんだが、全く同じで
片方だけおかしいとかいうことはないはずだしなんか違いがあるん
だろう。

255:nobodyさん
09/11/20 16:12:32
if ($ENV{'REQUEST_METHOD'} eq "POST") {
 read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
 @pairs = split(/&/,$buffer);
 for $pair (@pairs) {
 ($name, $value) = split(/=/, $pair);
 $value =~ tr/+/ /;
 $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
 Encode::from_to($value, 'utf8', 'utf8');
 $in{$name} = $value;
}

のようなありきたりのフォーム取得構文を
enctype="multipart/form-data"
に対応させるために

use CGI;
my $query = CGI->new;
my $user = $query->param('user');
のような構文を使って

$in{'name'}=$value形式で受けとりたいのですが
どのように記述したらよいでしょうか?


256:nobodyさん
09/11/20 16:45:27
>>255
use CGI;
my $query = CGI->new;
*in = $query->Vars();

257:nobodyさん
09/11/20 17:56:52
>>256
ありがとう動いた

258:nobodyさん
09/11/20 18:50:54
もうちょっとだけお付き合いください

フォーム側で
<input type="file" name="tempfile">としたものを

>>256 の方法で受け取り
open(SAVE,"> up.jpg");
binmode(SAVE);
binmode(STDOUT);
print SAVE $tempfile;
close(SAVE);
で保存すると、up.jpgというファイルの中身に
添付ファイルのバイナリでなく、
アップロードしたファイル名のみがテキストで記述されてました。

この場合は、$in{'tempfile'}の中身にはファイル名しか格納されていないことになります

enctype="multipart/form-data"の場合は別の変数になるのでしょうか?

259:nobodyさん
09/11/20 19:46:05
>>258
こうすると、うまくいきます?

print SAVE $tempfile;

   ↓   ↓

print SAVE <$tempfile>;

260:nobodyさん
09/11/20 21:19:20
てすと

261:258
09/11/20 21:42:40
>>259
ダメでしたorz
結果は同じでした

262:258
09/11/20 21:51:20
っしゃ!解決できました
調べてみたら、Varsとparamを両方つかわないといけないっぽいです

use CGI;
#データの取得 $in{'name'}で取得
if ($ENV{'REQUEST_METHOD'} eq "POST") {
 my $query = CGI->new;
 *in = $query->Vars();
}
#ファイルの取得
my $query = CGI->new;
$upfile= $query->param('tempfile');
#ファイルの書込
open(SAVE,"> up.jpg");
binmode(SAVE);
binmode(STDOUT);
while (read($upfile, $buffer, 1024)) {
 print SAVE $buffer;
}
close(SAVE);

263:nobodyさん
09/11/23 03:37:20
 $a=x,$a=y,$a=z・・・それぞれの条件で動作分岐
させるとき、ifとelsifで書いていくのはなんか非効率的
のような。なんか方法あるのでしょうか?

264:nobodyさん
09/11/23 05:58:26
何を持って非効率というのかわからん

あと、サンプルでも$a,$bは使わぬが吉

265:nobodyさん
09/11/23 06:40:31
>>263
switchが欲しいってことだろ
Perlのバージョンが5.10以上なら

use feature qw/:5.10/;
given($a){
 when(x){…}
 when(y){…}
 …
}

と書ける

266:nobodyさん
09/11/23 07:58:49
三項演算子使え。
$a =(条件1) ? 'x'
  :(条件2) ? 'y'
  :      'z'
  ;


267:nobodyさん
09/11/23 09:00:29
三項演算子って二者択一の時はよく使うけど、
長い式になると優先順位がわかりづらくて使いづらい。。。

268:nobodyさん
09/11/23 09:19:12
>>263
5.10未満ならSwitchモジュールを

switch文
URLリンク(www2u.biglobe.ne.jp)

269:nobodyさん
09/11/23 09:35:35 XYWla5BP
連想配列に呼ぶべき関数へのリファレンスぶち込んじゃってる
ただこれをやると関数への引数は連想配列へのリファレンスにならざるを得ないから、あまりやらないけど・・・

270:nobodyさん
09/11/23 10:26:54
>>269
こんな感じ?

my %func = ( foo => \&foo, bar => \&bar );

$func{foo}(1, 2); #=> 1 2 in foo

sub foo {
print "@_ in foo";
}

sub bar {
print "@_ in bar";
}

>関数への引数は連想配列へのリファレンスにならざるを得ない
これはどういう意味ですか?


最新レス表示
レスジャンプ
類似スレ一覧
スレッドの検索
話題のニュース
おまかせリスト
オプション
しおりを挟む
スレッドに書込
スレッドの一覧
暇つぶし2ch