xiaoyafeng has asked for the wisdom of the Perl Monks concerning the following question:

I found the list operator(..) in 32bit perl is very mysterious. Take a look below codes:
#1: perl -E"my @aa = 1..20_000_000; my @bb = 1..20_000_000;" #error! out o +f memory! #2: perl -E"my @aa = 1..20_000_000; my @bb = @aa;" #works well #3: perl -e"my @cc = 1..40_000_000" #error! out of memory #4: perl -E"my @cc; for(my $i = 1; $i<40_000_001; $i++){ push @cc, $i;} pr +int scalar @cc" #works well. #5: perl -e"push @cc,$_ for 1..40_000_000; print scalar @cc;" works well
Could anyone tell me how implement range operator in perl source? I can't figure out how example 1 and 4 is broken.
Thanks!!

UPDATE1: add example 5

UPDATE2: choroba perfectly answer my question, thankss





I am trying to improve my English skills, if you see a mistake please feel free to reply or /msg me a correction

Replies are listed 'Best First'.
Re: strange list operator
by choroba (Cardinal) on Oct 09, 2015 at 08:36 UTC
    That's because list assignment is not optimized.
    1. 4 long lists involved: @aa, @bb, 1 .. 2e7 twice, size 8e7;
    2. 3 lists involved, @aa, @bb, 1 .. 2e7, size 6e7;
    3. 2 lists involved, @cc, 1 .. 4e7, size 8e7;
    4. 1 list involved, size 4e7.
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      But how explain example 5?




      I am trying to improve my English skills, if you see a mistake please feel free to reply or /msg me a correction

        List assignment is not optimized, but for is.
        لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: strange list operator
by Tux (Canon) on Oct 09, 2015 at 08:51 UTC

    What perl version? I seem to remember that there has been an optimization where older perls created the range on stack before copying it to the array and newer perls set the values directly.


    Enjoy, Have FUN! H.Merijn
      Summary of my perl5 (revision 5 version 12 subversion 4) configuration +: Platform: osname=MSWin32, osvers=5.2, archname=MSWin32-x86-multi-thread uname='' config_args='undef' hint=recommended, useposix=true, d_sigaction=undef useithreads=define, usemultiplicity=define useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=und +ef use64bitint=undef, use64bitall=undef, uselongdouble=undef usemymalloc=n, bincompat5005=undef
      that means all list assignment will use the same stack?




      I am trying to improve my English skills, if you see a mistake please feel free to reply or /msg me a correction

Re: strange list operator
by Discipulus (Canon) on Oct 09, 2015 at 08:35 UTC
    i suspect you are hitting the limit of an address of the 32 bit arch..
    See interesting discussion here at perlMonks: maximum value of a scalar

    L*
    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
      Thanks for your reply, I add example 5. looks it works well but also hit limit.




      I am trying to improve my English skills, if you see a mistake please feel free to reply or /msg me a correction

Re: [Resolved?] strange list operator (tied array)
by mr_ron (Deacon) on Oct 09, 2015 at 15:59 UTC

    There sort of is a way to "implement range operator in perl source". Perl has a feature called tying that lets you implement indexing on an array yourself and lets you return something like the index of the element as the value. I have included a bare bones implementation of an array whose values are a sequence below. The solution has virtually no memory limitation on the size of the sequence.

    package Tie::SeqArray; use strict; use warnings; use parent 'Tie::Array'; sub TIEARRAY { my $self = shift; my $class = ref($self) || $self; my $sequence_size = shift || die "sequence size of at least one re +quired"; return bless {seq_size => $sequence_size}; } sub FETCH { my $self = shift; my $i = shift; return $i >= 0 && $i < $self->{seq_size} ? $i +1 : undef; } sub FETCHSIZE { my $self = shift; return $self->{seq_size}; } package main; use strict; use warnings; # from Perl Cookbook http://docstore.mik.ua/orelly/perl/cookbook/ch02_ +18.htm sub commify { my $text = reverse $_[0]; $text =~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1_/g; return scalar reverse $text; } my (@aa, @bb); tie @aa, 'Tie::SeqArray', 20_000_000; tie @bb, 'Tie::SeqArray', 20_000_000; print $aa[100], ' ', commify(scalar(@aa)), "\n"; print commify($bb[19_999_001]), ' ', commify(scalar(@bb)), "\n"; __END__ 101 20_000_000 19_999_002 20_000_000
    Ron
Re: strange list operator
by Anonymous Monk on Oct 09, 2015 at 08:40 UTC

    Could anyone tell me how implement range operator in perl source?

    What?

    I can't figure out how example 1 and 4 is broken.

    How much ram do you have?

    If 1..10_000_000 takes about 500mb, 4 times as much is going to take about 2GB ... which is about the limit for some systems

    Running out of ram doesn't mean they're broken