凄く今更。
Perl で新規スクリプトを書く予定もないし、こんなコードを使う気もない。
ただ、記憶の奥底に沈めた訳分らんコードが目についた以上、放置するのは奥歯にものが
挟まったみたいで嫌だったので。
本稿のプログラムは全て use strict; use warnings;
の下、動作します。
[2024/07/08]
本稿は、結局は型グロブを利用してました。ってだけの記事です。
なので、本稿を読むより、型グロブの本格的な解説記事を読まれる方が良いかと思います。
発端
% perl -le '0->[0] = 100; print 0->[0];' -Mstrict -Mwarnings
100
え、、、何これ。1
左辺値が裸の 0
で始まってるのに、怒られてないよ?
何でリファレンスなの?
B::Deparse
したら $0[0]
のことだって。何でこう書けるの?
利用している機能
配列・連想配列の型グロブ(*Foo::Bar
)利用時に、何にアクセスするか自明の場合は *
を省略出来る模様。その代りクォーテーションで括る必要がある。 2
型グロブで、%main::h
へ値の代入。print 時には ->{}
でハッシュにアクセスしているのは明白
% perl -le '*main::h = { 10, 11} ; print *main::h->{10};'
11
なので、以下の様に記載出来る。
% perl -le '"main::h"->{10} = 11 ; print "main::h"->{10};'
11
時々、CPAN モジュールの中とかで見られる書き方ではあるけど、普通は使わない。
型グロブでのパッケージ名の省略
型グロブでは、メインパッケージの場合、パッケージ名の省略が可能
% perl -le '*h = { 10, 11} ; print *h->{10};' -Mstrict -Mwarnings
11
定義済みの変数への適用
上記の機能は、当然、 定義済みの変数(配列・連想配列)への代入にも使える。
- Perl の定義済みの変数は、main パッケージのパッケージ変数である
-
$\d+
,@\d+
,%\d+
は定義済みのリストには載っていないものの、実質定義済みの変数として扱われる
従って 1. については以下の様にコードが書ける。
%ENV に値を追加したり
% perl -le '"ENV"->{TEST} = "test"; print Dumper \%ENV;' -MData::Dumper
$VAR1 = {
(前略)
'TEST' => 'test',
(後略)
};
$ARGV[0] を変更したり
% cat test.txt
hoge
% perl -lpe 'BEGIN{ "ARGV"->[0] = "test.txt" }'
hoge
で、2.。
perl では変数名として、シジルの直後に数字のみで構成された文字列が使用可能である。3
定義済みとして扱われているので、当然変数名宣言無しでも use strict; use warnings;
が通る。
% perl -le '@0 = (100); print $0[0];'
と言うことで、型グロブで記載すると
# perl -le '*0 = [ 100 ]; print *0->[0];'
% perl -le '*0->[0] = 100; print *0->[0];'
100
で、*
を省略
% perl -le '0->[0] = 100; print 0->[0];'
100
"0"->[0]
じゃなくて 0->[0]
で機能するのは、Perl のご都合主義の成せる技。(まあ、単に数値だから。)
% perl -MDevel::Peek -e '0->[0] = 100; Dump(@0);'
SV = PVAV(0x12500d2f0) at 0x1250173a8
REFCNT = 1
FLAGS = ()
ARRAY = 0x124e0b3e0
FILL = 0
MAX = 3
FLAGS = (REAL)
Elt No. 0
SV = IV(0x12500bc00) at 0x12500bc10
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 100 # <= Integer 100 が入ってますよ
改めて調べようとすると4、Google 先生はボケちゃってるし、(無料版) ChatGPT 先生は頓珍漢な答えしかしてくれないし、質問サイトにも Perl 古参の方々は居なさそうだし、有用なサイトは沈んでるか消えてるし5、 寂しいものだ。
BTW
あ、B::Deparse
の穴みっけ
% perl -le '0->[0] = 100 ; package HOGE; "HOGE::0"->[0] = 10; print "HOGE::0"->[0]; print 0->[0]; 1;'
10
100
↓
% perl -le '0->[0] = 100 ; package HOGE; "HOGE::0"->[0] = 10; print "HOGE::0"->[0]; print 0->[0]; 1;' -MO=Deparse
BEGIN { $/ = "\n"; $\ = "\n"; }
$0[0] = 100;
package HOGE;
$0[0] = 10;
print $0[0];
print $0[0];
'???';
-e syntax OK
↓
% perl -le '0->[0] = 100 ; package HOGE; "HOGE::0"->[0] = 10; print "HOGE::0"->[0]; print 0->[0]; 1;' -MO=Deparse | grep -v '???' | perl
-e syntax OK
10
10
つか、定義済み変数の"暗黙の main パッケージ変数である"って挙動に対応していないのかな、、、でもないね。
% perl -le '"ENV"->{"T"} = "test" ; package HOGE; "HOGE::ENV"->{"T"} = "HOGE"; print "HOGE::ENV"->{"T"}; print "ENV"->{"T"}; 1;' -MO=Deparse
BEGIN { $/ = "\n"; $\ = "\n"; }
$ENV{'T'} = 'test';
package HOGE;
$HOGE::ENV{'T'} = 'HOGE';
print $HOGE::ENV{'T'};
print $ENV{'T'};
'???';
-e syntax OK
-
どこぞのページで見付けたコードから。古いページだし、解説もされてないし、敢てリンクしません。 ↩
-
但し、perldoc 内でそれらしき説明には行きあたっていない ↩
-
perldoc perldata
の変数名の項の下部参照。ちなみにスカラについては、$0
がperldoc perlvar
に記載の定義済み変数、記載はないものの$1
からの 0 埋めされていない数値は、正規表現マッチ結果の入った変数として使われる。それ以外 - 0 が先頭のもの($010
) など - は使われていない。 ↩ -
自分自身も型グロブが思い当たらず、ずいぶん遠まわりしてしまった。ここまで、ボケるものか ↩
-
KENT WEB が生き残ってるのに驚愕した! Copyright が 2023 だから、少なくとも去年まではメンテされているの? ↩