如何让 Perl 将整数存储为数字而不是字符串?
How can I make Perl store integers as numbers instead of strings?
我正在将文本文件中的许多数字解析为由键和对值数组的相应引用组成的哈希条目。使用 Devel::Peek 和 Devel::Size 我注意到数字的字符串表示形式存储在这个数据结构中,这会浪费内存。我怎样才能摆脱这些字符串表示的记忆(换句话说,我怎样才能把一个 PVIV 变成一个 IV)?
对它们应用 "numify operator" 0+
。
use strict;
use warnings;
use Devel::Peek;
# PVIVs (strings that were used in a numeric context)
my @values = grep 0+$_, qw/123 234/;
my %hash = ( "key" => [ @values ] );
Dump \%hash;
# make them just IVs
%hash = ( "key" => [ map 0+$_, @values ] );
Dump \%hash;
输出:
SV = IV(0x7fcaf401d9d0) at 0x7fcaf401d9e0
REFCNT = 1
FLAGS = (TEMP,ROK)
RV = 0x7fcaf4025290
SV = PVHV(0x7fcaf400ac60) at 0x7fcaf4025290
REFCNT = 2
FLAGS = (SHAREKEYS)
ARRAY = 0x7fcaf3c1ad00 (0:7, 1:1)
hash quality = 100.0%
KEYS = 1
FILL = 1
MAX = 7
Elt "key" HASH = 0x11e2db55
SV = IV(0x7fcaf401d928) at 0x7fcaf401d938
REFCNT = 1
FLAGS = (ROK)
RV = 0x7fcaf401d908
SV = PVAV(0x7fcaf4005c58) at 0x7fcaf401d908
REFCNT = 1
FLAGS = ()
ARRAY = 0x7fcaf3c04550
FILL = 1
MAX = 1
FLAGS = (REAL)
Elt No. 0
SV = PVIV(0x7fcaf4021080) at 0x7fcaf401d920
REFCNT = 1
FLAGS = (IOK,POK,IsCOW,pIOK,pPOK)
IV = 123
PV = 0x7fcaf3c04900 "123"[=11=]
CUR = 3
LEN = 10
COW_REFCNT = 2
Elt No. 1
SV = PVIV(0x7fcaf4021098) at 0x7fcaf401d950
REFCNT = 1
FLAGS = (IOK,POK,IsCOW,pIOK,pPOK)
IV = 234
PV = 0x7fcaf3c0e2b0 "234"[=11=]
CUR = 3
LEN = 10
COW_REFCNT = 2
SV = IV(0x7fcaf401d9d0) at 0x7fcaf401d9e0
REFCNT = 1
FLAGS = (TEMP,ROK)
RV = 0x7fcaf4025290
SV = PVHV(0x7fcaf400ac60) at 0x7fcaf4025290
REFCNT = 2
FLAGS = (SHAREKEYS)
ARRAY = 0x7fcaf3c1ad00 (0:7, 1:1)
hash quality = 100.0%
KEYS = 1
FILL = 1
MAX = 7
Elt "key" HASH = 0x11e2db55
SV = IV(0x7fcaf40252f8) at 0x7fcaf4025308
REFCNT = 1
FLAGS = (ROK)
RV = 0x7fcaf401d9f8
SV = PVAV(0x7fcaf4005ca8) at 0x7fcaf401d9f8
REFCNT = 1
FLAGS = ()
ARRAY = 0x7fcaf3c0c6d0
FILL = 1
MAX = 1
FLAGS = (REAL)
Elt No. 0
SV = IV(0x7fcaf401da78) at 0x7fcaf401da88
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 123
Elt No. 1
SV = IV(0x7fcaf401da60) at 0x7fcaf401da70
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 234
首先,如果您想在这个级别上节省内存,Perl 可能不适合您。 Perl 在提供速度优势时肆意 "wastes" 内存。
$ perl -e'
use feature qw( say );
use Devel::Size qw( size );
sub f {
my $x;
say size($x);
$x = "x" x 100;
say size($x);
}
f() for 1..2;
'
24
134
134
134
0+$scalar
和 int($scalar)
return 都是 SVt_IV
或 SVt_NV
类型的标量。这些都行。
$ perl -e'
use feature qw( say );
use Devel::Size qw( size );
my $x = 1234567890;
my $y = "1234567890";
say size($x);
say size($y);
say size([=11=]+$y);
say size(int($y));
'
24
44
24
24
无法降级现有标量,但您可以通过 "aliasing" 替换它。
$ perl -e'
use feature qw( say );
use experimental qw( refaliasing );
use Devel::Size qw( size );
my $x = 1234567890;
my $y = "1234567890";
say size($x);
say size($y);
$y = \(0+$y);
say size($y);
'
24
44
24
我正在将文本文件中的许多数字解析为由键和对值数组的相应引用组成的哈希条目。使用 Devel::Peek 和 Devel::Size 我注意到数字的字符串表示形式存储在这个数据结构中,这会浪费内存。我怎样才能摆脱这些字符串表示的记忆(换句话说,我怎样才能把一个 PVIV 变成一个 IV)?
对它们应用 "numify operator" 0+
。
use strict;
use warnings;
use Devel::Peek;
# PVIVs (strings that were used in a numeric context)
my @values = grep 0+$_, qw/123 234/;
my %hash = ( "key" => [ @values ] );
Dump \%hash;
# make them just IVs
%hash = ( "key" => [ map 0+$_, @values ] );
Dump \%hash;
输出:
SV = IV(0x7fcaf401d9d0) at 0x7fcaf401d9e0
REFCNT = 1
FLAGS = (TEMP,ROK)
RV = 0x7fcaf4025290
SV = PVHV(0x7fcaf400ac60) at 0x7fcaf4025290
REFCNT = 2
FLAGS = (SHAREKEYS)
ARRAY = 0x7fcaf3c1ad00 (0:7, 1:1)
hash quality = 100.0%
KEYS = 1
FILL = 1
MAX = 7
Elt "key" HASH = 0x11e2db55
SV = IV(0x7fcaf401d928) at 0x7fcaf401d938
REFCNT = 1
FLAGS = (ROK)
RV = 0x7fcaf401d908
SV = PVAV(0x7fcaf4005c58) at 0x7fcaf401d908
REFCNT = 1
FLAGS = ()
ARRAY = 0x7fcaf3c04550
FILL = 1
MAX = 1
FLAGS = (REAL)
Elt No. 0
SV = PVIV(0x7fcaf4021080) at 0x7fcaf401d920
REFCNT = 1
FLAGS = (IOK,POK,IsCOW,pIOK,pPOK)
IV = 123
PV = 0x7fcaf3c04900 "123"[=11=]
CUR = 3
LEN = 10
COW_REFCNT = 2
Elt No. 1
SV = PVIV(0x7fcaf4021098) at 0x7fcaf401d950
REFCNT = 1
FLAGS = (IOK,POK,IsCOW,pIOK,pPOK)
IV = 234
PV = 0x7fcaf3c0e2b0 "234"[=11=]
CUR = 3
LEN = 10
COW_REFCNT = 2
SV = IV(0x7fcaf401d9d0) at 0x7fcaf401d9e0
REFCNT = 1
FLAGS = (TEMP,ROK)
RV = 0x7fcaf4025290
SV = PVHV(0x7fcaf400ac60) at 0x7fcaf4025290
REFCNT = 2
FLAGS = (SHAREKEYS)
ARRAY = 0x7fcaf3c1ad00 (0:7, 1:1)
hash quality = 100.0%
KEYS = 1
FILL = 1
MAX = 7
Elt "key" HASH = 0x11e2db55
SV = IV(0x7fcaf40252f8) at 0x7fcaf4025308
REFCNT = 1
FLAGS = (ROK)
RV = 0x7fcaf401d9f8
SV = PVAV(0x7fcaf4005ca8) at 0x7fcaf401d9f8
REFCNT = 1
FLAGS = ()
ARRAY = 0x7fcaf3c0c6d0
FILL = 1
MAX = 1
FLAGS = (REAL)
Elt No. 0
SV = IV(0x7fcaf401da78) at 0x7fcaf401da88
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 123
Elt No. 1
SV = IV(0x7fcaf401da60) at 0x7fcaf401da70
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 234
首先,如果您想在这个级别上节省内存,Perl 可能不适合您。 Perl 在提供速度优势时肆意 "wastes" 内存。
$ perl -e'
use feature qw( say );
use Devel::Size qw( size );
sub f {
my $x;
say size($x);
$x = "x" x 100;
say size($x);
}
f() for 1..2;
'
24
134
134
134
0+$scalar
和 int($scalar)
return 都是 SVt_IV
或 SVt_NV
类型的标量。这些都行。
$ perl -e'
use feature qw( say );
use Devel::Size qw( size );
my $x = 1234567890;
my $y = "1234567890";
say size($x);
say size($y);
say size([=11=]+$y);
say size(int($y));
'
24
44
24
24
无法降级现有标量,但您可以通过 "aliasing" 替换它。
$ perl -e'
use feature qw( say );
use experimental qw( refaliasing );
use Devel::Size qw( size );
my $x = 1234567890;
my $y = "1234567890";
say size($x);
say size($y);
$y = \(0+$y);
say size($y);
'
24
44
24