読者です 読者をやめる 読者になる 読者になる

北海道苫小牧市出身の壮年PGが書くブログ

永遠のプログラマを夢見る、苫小牧市出身のおじさんのちらしの裏

定数とシンボルテーブルのメモ

perl perl+web

調べたので自分用のメモ。

perldeltaを見てみると、以下のように書いてます。perl5.10.xから、シンボルテーブルにリファレンスを入れるタイプの定数の実装もあるみたいです*1

The interpreter internals now support a far more memory efficient form of inlineable constants. Storing a reference to a constant value in a symbol table is equivalent to a full typeglob referencing a constant subroutine, but using about 400 bytes less memory.

perl5100delta

サンプルコード。なるほど。

use strict;
use warnings;
BEGIN { $main::{FOO} = \'foo foo'; }
print FOO, "\n";

__END__

実行結果:
foo foo

constant.pm 的には以下のようなコードが。これを見る限りは、上のようなコードは気軽に使わない方がいいのかもしれないです。

		# The constant serves to optimise this entire block out on
		# 5.8 and earlier.
		if (_CAN_PCS && $symtab && !exists $symtab->{$name}) {
		    # No typeglob yet, so we can use a reference as space-
		    # efficient proxy for a constant subroutine
		    # The check in Perl_ck_rvconst knows that inlinable
		    # constants from cv_const_sv are read only. So we have to:
		    Internals::SvREADONLY($scalar, 1);
		    $symtab->{$name} = \$scalar;
		    ++$flush_mro;
		}

constant.pm

ちなみに、この動作のせいでシンボルテーブルには型グロブ以外も入っているので、以下のコードは5.8.xでは動きましたが、5.10.x以降のperlではエラーとなりました*2

use strict;
use warnings;
use constant FOO => 'foo foo';
print *{$::{FOO}}{CODE}->(), "\n";

__END__

結果(5.12.1):
Not a GLOB reference at - line 4.

*1:5.8.xばかり使ってたので今まで気がつかなかったorz

*2:そして職場のレガシーコードの中にこんな処理が入っていた、と。