[kansaipm] Re: self.pl

mishima at momo.so-net.ne.jp mishima at momo.so-net.ne.jp
Sun Apr 22 04:09:39 CDT 2001


三嶋@奈良です。

この度は、一周年記念イベントに参加してくださったみなさん、スタッフとし
て携わってくださったみなさん、本当にどうもありがとうございました。

クイズ大会は Kansai.pm として初めての試みであったにも関わらず、みなさ
まのご協力(当日のミスに対する、参加者からのツッコミ等含む ^^)により、
たいへん楽しいものとなりました。来年またやりたいですね。

さて、当日紹介できなかった、self.pl の解答例の紹介ですが、結城浩さんの
PerlQuizで実際にあった解答は、以下のURLから参照することができます。

http://backno.mag2.com/reader/BackBody?id=200002082310000000015670000

解答は大きく分けて3種類あります。

(A) 空のスクリプト。
(B) スクリプトファイル自身を開いて出力するもの。
(C) 何らかの形で処理を二重に書いて、スクリプトの内容と出力を一致させるもの。

以下、中島さんのメールに対するコメントですが...

From: Yasushi Nakajima <sey at jkc.co.jp>
Subject: [kansaipm] self.pl
Date: Sat, 21 Apr 2001 20:40:26 +0900

>  さて、今日のクイズの中で、実行するとそのスクリプトファイルをcatあるい
> はtypeするのと同じ表示をするスクリプトを作れ、というのがありました。非常
> にトリッキーな回答である「空のスクリプト」というのは別として、
> 
> 1)もっとも素直な回答
>   open(F,$0);print <F>;close(F);
> 
> 2)少しずぼらをした回答
>   @ARGV=$0;print<>;

このあたりが、典型的な (B) の例ですね。
バリエーションとしては、(OSに依存しますが) system や exec を用いて 
cat や type を呼び出す方法もあります。

> というのが今日の会場で出された回答かと思います。その後、帰りの京阪の中で
> 考えた結果、次の毛色の変わった答えを得ました。
> 
> 3)callerを使った回答
>   eval q(print 'eval q(',(caller(0))[6],');';);
> 
>  ただしこの3)は、残念ながらPerl4では動きません。5.00503と5.6.0で確認し
> ましたが、すべてのPerl5で動くかどうかは保証の限りではありません。

これは、(C)の例に当たると思います。
こういうのが解答として出たら、30点差し上げようと思っていました。

>  callerは、evalされた文字列の中で、引数付きで呼び出されると、7つ目の返
> 値としてevalされた文字列自身を返すという隠し機能(?)があります。今回の
> 問題のポイントは、Perlのスクリプト実行中に、どうやって実行されているスク
> リプトの内容を文字列として得るか、というところにあります。スクリプトファ
> イルを読みとる(つまり上記の1)や2)の方法)以外には、このcallerの7番目の
> 返値を使うしか方法はないように思います。もしこれ以外の方法があればぜひ教
> えてください。

ほえー、知りませんでした。caller に引数を渡すと返り値が増えるんですね。
上記 URL から参照できる解答例に、いくつか別解がありますので、ご参照
ください。

なお、結城浩さんのPerlQuizの購読申し込みは http://www.hyuki.com/pq/ から、
バックナンバーの閲覧は http://backno.mag2.com/reader/Back?id=0000015670 
から行なうことができます。

中島さんは、Perlに関する造詣が非常に深くていらっしゃるようですので、
次回は問題を作成する側として参加していただけると、非常にありがたいです。
#そうすれば、私が参加者の側に回れますし。(^^;

冗談はさておき(7割本気ですが ^^;)、今後ともよろしくお願いいたします。

--
$p='Perl';$_='MISHIMA Masahiro';tr/A-Z/c-u/;tr/iron or steel/t/;
sub _ {pack'c*',$x=110+ at _*5,$x+1}@x=(sort(grep{!$_{$_}++}split//),
$p=~/(.(..).)/);$x[5]=~s/^/_/e;$x[6].=_ 1;for(@w=(47,1639,8,31259))
{s/\d/$x[$&-1]/g}print ucfirst "@w.\n";




More information about the Kansai-pm mailing list