perlで eval 'use〜 ってどういうこと!

[上に] [前に] [次に]
P初心者 1999/12/14(火) 18:35:11
以下が理解できません!

eval 'use Oraperl; 1' || dei $@ if $] >= 5;

実は use と require の違いもよくわかりません。
本には use = require + シンボルのインポート機能
みたいなことが書いてありましたが、
シンボルのインポート機能ってわかりません。
細かいところですが、Oraperl; 1 の 後ろの 1 ってなに?

こんなこと、本で調べればわかるでしょ〜って言われそうですが、
結構調べましたが、わかりませんでした。いいパール本を持ってなくて...。
よろしくお願い致します。

J.Naka 1999/12/14(火) 21:21:00
これ、注視です。
#実は、自分の分かっていると思う範囲をレスとして書いたのだけど、あまりに範囲が狭く幼稚なので消してしまいました(^^;;

J.Naka 1999/12/14(火) 21:45:30
やっぱし、自分が解かってると思われる範囲を書いてみます
#チャット状態回避(^^;
-------------------------
require で取り込んだファイル(モジュール)内のシンボル(関数や変数など)は、パッケージ名を前置しないとアクセスできない。これをエクスポートというのかな?

useで取り込んだファイル内のシンボルは、前置無しで元々あるがの如くアクセスできる。これをインポートという。
-------------------------
こんなところです(^^; 今は、変数(シンボル=スカラー)アクセスに的を絞ったレポート制作中です。添削希望でやってます。よろしくね>先輩諸氏

ふじ 1999/12/14(火) 22:11:11
>eval 'use Oraperl; 1' || dei $@ if $] >= 5;
eval 'use Oraperl; 1' || die $@ if $] >= 5;
ですよね?(dei ではなくて、 die )

eval は、実行してエラーが出なければ最後に評価した式の値を返します。

eval 'use Oraperl;1'
は、use Oraperl でエラーが出なければ 1; が評価されるので、
全体としては真。 || 以降は評価されない。
# use って、成功した場合何を返すんだろう?

エラーが出ると eval は $@ にエラーメッセージをセットして、未定義値を返す
ので、|| 以降が評価される。

die $@ if $] >= 5;

$] は Perl のバージョン番号。$@ はevalがセットしたエラーメッセージが入っているから、
「Perl のバージョンが 5 以上なら、$@ を出力して死ね」
# $] とか $@ 等の特殊変数は、ラクダ本で解説されています。

perl4 以前だと use が確実にエラーになるので、4の場合は
この文では何も起きません。

zizz... [HomePage] 1999/12/14(火) 22:17:06
deiってdieの間違いみたいだ。

evalは保険をかけている。
evalで実行すれば、致命的エラーでも死なない。
$@は発生したエラーが入る。

> 細かいところですが、Oraperl; 1 の 後ろの 1 ってなに?
うまくいったら真をかえす。

$]は perl -v で表示される文字列が入っている。
$] >= 5
はPerl 5以上。

zizz... [HomePage] 1999/12/14(火) 22:18:39
重なった。しかも向こうのほうが丁寧。

mm 1999/12/15(水) 02:24:57
>perl4 以前だと use が確実にエラーになるので、
perl4だと、if 修飾子の条件式が偽となるので、evalも実行されないです。

>evalで実行すれば、致命的エラーでも死なない。
use って eval できるものなのでしょうか?
use はコンパイル時に解釈され、eval は実行時なので、
eval中では、BEGINブロックが実行できないと思うのですが…?

B-Cus 1999/12/15(水) 02:40:08
> eval中では、BEGINブロックが実行できないと思うのですが…?
eval したとき、その中に BEGIN ブロックがあったら
(eval に渡したコードのうち) 一番最初に実行されるんじゃないですかね。

ので、問題ないと思います。

ふじ 1999/12/15(水) 02:57:36
>perl4だと、if 修飾子の条件式が偽となるので、evalも実行されないです。
でした。結合の強さを勘違いしてました。

if $]>=5 は eval 'use Oraperl; 1' || dei $@  全体に掛かるんですね。
御指摘ありがとうございました。

B-Cus 1999/12/15(水) 02:58:48
ところで、
  foo if bar;
って、foo 内にどんな演算子を置いても
  (foo) if bar;
として解釈されるんでしたっけ。
# if(while/until/unless) 修飾子より結合が強い演算子はあるか、ということ。ないよね?

B-Cus 1999/12/15(水) 03:02:26
> 結合が強い演算子はあるか
逆か。「弱い演算子はあるか」でした。

mm 1999/12/15(水) 03:12:39
>ので、問題ないと思います。
なるほど。
ちょっと試してみたら、evalによりuseしても、
モジュール内へのアクセス部分でエラーになったので、
構文的に BIGIN はブロックで囲めないんだと勘違いしたようです。
モジュールへのアクセス部分もevalしてやれば、問題なく動きました。

>  (foo) if bar;
>として解釈されるんでしたっけ。
文の最後のセミコロンの前に1個置けるということなので、
()で括る優先順位の問題ではないと思いますが、
最弱の or よりも結合は弱いようです。

B-Cus 1999/12/15(水) 03:24:19
> モジュール内へのアクセス部分でエラーになったので、
ああ、そうか。eva ると別パッケージになって(?)、シンボルが
無効になっちゃうのね。例えば
  eval 'use Socket';
  socket(SOCKET,PF_INET,SOCK_STREAM,0);
だと、PF_INET/SOCK_STREAM が未設定になると。気が付きませんでした。
しかし、eval { use ... }; だと OK なようです。

> 最弱の or よりも結合は弱いようです。
なるほど。
   eval 'use Oraperl; 1' or die $@ if $] >= 5;
ならまた違うわけですな。

mm 1999/12/15(水) 03:41:16
>ならまた違うわけですな。
いや、|| や or よりもif修飾子の方が結合が弱いので、
結果は変わらないと思います。

チャット状態と言われそうなので、
eval BLOCKの件はもうちょっと調べます(苦笑)

ふじ 1999/12/15(水) 04:27:09
> eval { use ... }; だと OK なようです。
でも eval BLOCK だと、コンパイル時のエラートラップには使えないみたいですね。

% perldoc perlfunc
の eval の項には
> checking the code within BLOCK at compile time.
とあります。

perl -e 'eval {use zzz;1} || die "run-time error"'
はコンパイルエラーで、
perl -e 'eval "use zzz;1" || die "run-time error"'
は実行時エラー。

perl -e 'eval "use xxx;1" || die "execution error" if $] >=6'
これでも、コンパイルエラーになります。

結局、
eval "use Hoge";
では、 Hogeのシンボルはインポートされない、ってことですよね。
# なら単に require して、パッケージ名付けてアクセスするのと同じ?

ふじ 1999/12/15(水) 04:31:49
#何度も確認したのに(;_;)

>perl -e 'eval "use xxx;1" || die "execution error" if $] >=6'
間違い。
perl -e 'eval {use xxx;1} || die "execution error" if $] >=6'
正しくは↑こっちです。

B-Cus 1999/12/15(水) 06:15:00
> いや、|| や or よりもif修飾子の方が結合が弱いので
う…。

> でも eval BLOCK だと、コンパイル時のエラートラップには使えないみたいですね。
うう…。


まとめると、モジュールから import せず、なおかつ
エラートラップしたいなら
  eval 'use Oraperl; 1' || die $@ if $] >= 5;
  eval 'require Oraperl; 1' || die $@ if $] >= 5;
  eval {require Oraperl; 1} || die $@ if $] >= 5;
いずれでも同じ。

一方、import しつつエラートラップすることはできない。
# @ISA 見ながら自分でモジュールを探したとしても、
# 結局 import できないから。

…でいいんですかね?


で、
> eval 'use Oraperl; 1' || die $@ if $] >= 5;
についてですが、一般論として、
  - モジュールが見付からないなら perl がエラーメッセージを出してくれる
  - モジュールがないとまともに動かない (モジュールが見付からなかったら
     それらを使わないように自前の関数を使って実行を続ける、というのは
     かなりめんどくさい。そもそも、それができるならモジュールを使う意味がない。
というわけで、use を eval してもあまり意味がないと思います。


##   eval 'use Socket';
##   eval 'print PF_INET,"\n"';
## が うまくいくので、$???::PF_INET とパッケージ名を
## 修飾すれば見れそうな気も。しかし、
##   eval 'use Socket';
##   map { print "$_ -> $main::{$_}\n" } sort keys %main::;
## の結果を見るに、main への import 自体はちゃんと行われている
## ようにも見える。わからんなぁ。

P初心者 1999/12/15(水) 09:58:43
>eval 'use Oraperl; 1' || die $@ if $] >= 5;
に関しては、ほぼ理解できました!

あと、$] ですが、私の本とふじさんが同じコト言っていますが、
>$]は perl -v で表示される文字列が入っている。
実際は 5.00404 みたいにバージョン番号のみの文字列ですねぇ!
(こういう細かなとことでつまずいてしまう)

みなさん、ありがとうございました!
私も早くみなさんのパールの話題に参加出来るレベルになりたいです!

Perl初心者 1999/12/15(水) 10:00:05
[[解決]]
解決マーク忘れました!

mm 1999/12/15(水) 13:12:08
>> checking the code within BLOCK at compile time.
>とあります。
この意味をちゃんと確認してから、って思って寝てしまいました(^^;

>## が うまくいくので、$???::PF_INET とパッケージ名を
>## 修飾すれば見れそうな気も。しかし、
修飾しても、evalを外すと、コンパイル時に名前が見つからないので、
エラーになると思います。

>## の結果を見るに、main への import 自体はちゃんと行われている
>## ようにも見える。わからんなぁ。
実行時に、evalが評価されて import されるのでは…?
keys %main:: も、実行時にevalの直後に評価されるので、その名前が取り出せる。
これに対して、eval外やevalのBLOCK内に名前が直接書いてあると、
実行の前のコンパイル時に引っ掛かってしまうということだと思いますが。

[上に] [前に] [次に]