[31368] in Perl-Users-Digest

home help back first fref pref prev next nref lref last post

Perl-Users Digest, Issue: 2620 Volume: 11

daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Sat Oct 3 00:09:43 2009

Date: Fri, 2 Oct 2009 21:09:08 -0700 (PDT)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)

Perl-Users Digest           Fri, 2 Oct 2009     Volume: 11 Number: 2620

Today's topics:
    Re: CGI and UTF-8 <ben@morrow.me.uk>
    Re: CGI and UTF-8 sln@netherlands.com
    Re: CGI and UTF-8 <hjp-usenet2@hjp.at>
        FAQ 4.51 How do I permute N elements of a list? <brian@theperlreview.com>
        FAQ 5.14 How can I translate tildes (~) in a filename? <brian@theperlreview.com>
        FAQ 9.23 How do I find out my hostname, domainname, or  <brian@theperlreview.com>
    Re: machine dependent left shift results sln@netherlands.com
    Re: machine dependent left shift results <hjp-usenet2@hjp.at>
    Re: open() close() same file many times <m@rtij.nl.invlalid>
    Re: simple hash <netnews@invalid.com>
    Re: sort function warning, variable will not stay share <cartercc@gmail.com>
    Re: sort function warning, variable will not stay share <ben@morrow.me.uk>
    Re: sort function warning, variable will not stay share <cartercc@gmail.com>
    Re: sort function warning, variable will not stay share <uri@StemSystems.com>
    Re: sort function warning, variable will not stay share (Randal L. Schwartz)
    Re: Web-based two-column diff with color <s1037989@gmail.com>
        Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)

----------------------------------------------------------------------

Date: Fri, 2 Oct 2009 18:32:19 +0100
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: CGI and UTF-8
Message-Id: <32qhp6-unj1.ln1@osiris.mauzo.dyndns.org>


Quoth Helmut Richter <hhr-m@web.de>:
> 
> This is the same problem for *both* solutions offered in this thread:
> the utf8 pragma, and setting binmode on both STDIN and STDOUT. In fact, I 
> have the suspicion that the effect of the pragma is not much more than 
> such 
> a setting.

There's no need to suspect: read the docs. The only effect of the utf8
pragma is to tell perl that your source code is written in UTF-8. It has
no effect on the STDIO handles. (It *does* affect the DATA filehandle,
since that's what's used to read your source code.)

Ben



------------------------------

Date: Fri, 02 Oct 2009 11:31:16 -0700
From: sln@netherlands.com
Subject: Re: CGI and UTF-8
Message-Id: <svfcc55ug5k7s2akvk6kp8ps9vfb82g47j@4ax.com>

On Fri, 2 Oct 2009 17:04:04 +0200, Helmut Richter <hhr-m@web.de> wrote:

>On Mon, 28 Sep 2009, sln@netherlands.com wrote:
>
>> From the docs:
>> " PRAGMAS
>>   -utf8 
>>   This makes CGI.pm treat all parameters as UTF-8 strings.
>>   Use this with care, as it will interfere with the processing of binary uploads.
>
>This is the same problem for *both* solutions offered in this thread:
>the utf8 pragma, and setting binmode on both STDIN and STDOUT. In fact, I 
>have the suspicion that the effect of the pragma is not much more than 
>such 
>a setting.

Actually, this does NOT refer to use utf8; pragma, which is not a solution.
This is actually a parameter, a private symbol that CGI.pm uses. When set
by the user, CGI.pm does automatic parameter decoding (so you don't have to).
I haven't used CGI, why does STDIN need binmode set to utf8? For the same reason
STDOUT needs to be set?

Anyway, this is some code from CGI.pm (look at '-->' in margin that is marked)
and you should look at the actual module once in a while to glean some insight.
==============
# >>>>> Here are some globals that you might want to adjust <<<<<<
sub initialize_globals {
    ...
       # return everything as utf-8
-->    $PARAM_UTF8      = 0;
    ...
}
sub _setup_symbols {
    my $self = shift;
    my $compile = 0;

    # to avoid reexporting unwanted variables
    undef %EXPORT;

    foreach (@_) {
	$HEADERS_ONCE++,         next if /^[:-]unique_headers$/;
	$NPH++,                  next if /^[:-]nph$/;
	$NOSTICKY++,             next if /^[:-]nosticky$/;
	$DEBUG=0,                next if /^[:-]no_?[Dd]ebug$/;
	$DEBUG=2,                next if /^[:-][Dd]ebug$/;
	$USE_PARAM_SEMICOLONS++, next if /^[:-]newstyle_urls$/;
-->	$PARAM_UTF8++,           next if /^[:-]utf8$/;
	$XHTML++,                next if /^[:-]xhtml$/;
	$XHTML=0,                next if /^[:-]no_?xhtml$/;
	$USE_PARAM_SEMICOLONS=0, next if /^[:-]oldstyle_urls$/;
	$PRIVATE_TEMPFILES++,    next if /^[:-]private_tempfiles$/;
	$TABINDEX++,             next if /^[:-]tabindex$/;
	$CLOSE_UPLOAD_FILES++,   next if /^[:-]close_upload_files$/;
	$EXPORT{$_}++,           next if /^[:-]any$/;
	$compile++,              next if /^[:-]compile$/;
	$NO_UNDEF_PARAMS++,      next if /^[:-]no_undef_params$/;
	
	# This is probably extremely evil code -- to be deleted some day.
	if (/^[-]autoload$/) {
	    my($pkg) = caller(1);
	    *{"${pkg}::AUTOLOAD"} = sub { 
		my($routine) = $AUTOLOAD;
		$routine =~ s/^.*::/CGI::/;
		&$routine;
	    };
	    next;
	}

	foreach (&expand_tags($_)) {
	    tr/a-zA-Z0-9_//cd;  # don't allow weird function names
	    $EXPORT{$_}++;
	}
    }
    _compile_all(keys %EXPORT) if $compile;
    @SAVED_SYMBOLS = @_;
}
#### Method: param
# Returns the value(s)of a named parameter.
# If invoked in a list context, returns the
# entire list.  Otherwise returns the first
# member of the list.
# If name is not provided, return a list of all
# the known parameters names available.
# If more than one argument is provided, the
# second and subsequent arguments are used to
# set the value of the parameter.
####
sub param {
    my($self,@p) = self_or_default(@_);
    return $self->all_parameters unless @p;
    my($name,$value,@other);

    # For compatibility between old calling style and use_named_parameters() style, 
    # we have to special case for a single parameter present.
    if (@p > 1) {
	($name,$value,@other) = rearrange([NAME,[DEFAULT,VALUE,VALUES]],@p);
	my(@values);

	if (substr($p[0],0,1) eq '-') {
	    @values = defined($value) ? (ref($value) && ref($value) eq 'ARRAY' ? @{$value} : $value) : ();
	} else {
	    foreach ($value,@other) {
		push(@values,$_) if defined($_);
	    }
	}
	# If values is provided, then we set it.
	if (@values or defined $value) {
	    $self->add_parameter($name);
	    $self->{param}{$name}=[@values];
	}
    } else {
	$name = $p[0];
    }

    return unless defined($name) && $self->{param}{$name};

    my @result = @{$self->{param}{$name}};

-->    if ($PARAM_UTF8) {
-->         eval "require Encode; 1;" unless Encode->can('decode'); # bring in these functions
-->         @result = map {ref $_ ? $_ : Encode::decode(utf8=>$_) } @result;
       }

    return wantarray ?  @result : $result[0];
}
=====================



>
>>   It is better to manually select which fields are expected to return utf-8 strings
>>   and convert them using code like this:
>>   use Encode;
>>   my $arg = decode utf8=>param('foo');
>
>This is much less than half of the story. Getting a single parameter is a 
>fairly easy thing to do, with or without the CGI module.

As stated above, you can tell CGI.pm to decode ALL imput parameters for you,
taking care of having to individually do it.


>Using the CGI 
>module for producing HTML is only a very cumbersome way of writing 
>something in a complicated syntax that is much easier written directly in 
>HTML. For which task does the CGI module offer significant help, compared 
>with simply outputting HTML and analysing the input?
>
>One of the (relatively few) things that are easier with the CGI module 
>than without is reusing the input values as defaults for the same form 
>when it must be output again because of incompletely or wrongly filled-in 
>values. Now, if I have to touch every single value, decode it, and store 
>it back into the structure, I could have hand-programmed that reuse with 
>not more effort.

Yeah, there is no argument there. The Unicode (flavor utf-8) gatekeeper for
Perl is usually the file i/o layers which covers both input and output.
For example, the :utf8 layer on handles.

However, binary text can creep into data variables at various times and via
various paths. I guess its up to you to know where and when this can happen.
Decode in, encode out if thats the case. But don't encode more than once,
or data that hasen't been decoded.

-sln





------------------------------

Date: Fri, 2 Oct 2009 22:42:26 +0200
From: "Peter J. Holzer" <hjp-usenet2@hjp.at>
Subject: Re: CGI and UTF-8
Message-Id: <slrnhccpdi.q6k.hjp-usenet2@hrunkner.hjp.at>

On 2009-10-02 17:32, Ben Morrow <ben@morrow.me.uk> wrote:
> Quoth Helmut Richter <hhr-m@web.de>:
>> This is the same problem for *both* solutions offered in this thread:
>> the utf8 pragma, and setting binmode on both STDIN and STDOUT. In fact, I 
>> have the suspicion that the effect of the pragma is not much more than 
>> such 
>> a setting.
>
> There's no need to suspect: read the docs. The only effect of the utf8
> pragma is to tell perl that your source code is written in UTF-8.

I think he meant the -utf8 pragma of the CGI module, i.e.

use CGI qw/-utf8/;

	hp


------------------------------

Date: Sat, 03 Oct 2009 04:00:12 GMT
From: PerlFAQ Server <brian@theperlreview.com>
Subject: FAQ 4.51 How do I permute N elements of a list?
Message-Id: <g%zxm.310255$vp.40294@newsfe12.iad>

This is an excerpt from the latest version perlfaq4.pod, which
comes with the standard Perl distribution. These postings aim to 
reduce the number of repeated questions as well as allow the community
to review and update the answers. The latest version of the complete
perlfaq is at http://faq.perl.org .

--------------------------------------------------------------------

4.51: How do I permute N elements of a list?

    Use the "List::Permutor" module on CPAN. If the list is actually an
    array, try the "Algorithm::Permute" module (also on CPAN). It's written
    in XS code and is very efficient:

            use Algorithm::Permute;

            my @array = 'a'..'d';
            my $p_iterator = Algorithm::Permute->new ( \@array );

            while (my @perm = $p_iterator->next) {
               print "next permutation: (@perm)\n";
                    }

    For even faster execution, you could do:

            use Algorithm::Permute;

            my @array = 'a'..'d';

            Algorithm::Permute::permute {
                    print "next permutation: (@array)\n";
                    } @array;

    Here's a little program that generates all permutations of all the words
    on each line of input. The algorithm embodied in the "permute()"
    function is discussed in Volume 4 (still unpublished) of Knuth's *The
    Art of Computer Programming* and will work on any list:

            #!/usr/bin/perl -n
            # Fischer-Krause ordered permutation generator

            sub permute (&@) {
                    my $code = shift;
                    my @idx = 0..$#_;
                    while ( $code->(@_[@idx]) ) {
                            my $p = $#idx;
                            --$p while $idx[$p-1] > $idx[$p];
                            my $q = $p or return;
                            push @idx, reverse splice @idx, $p;
                            ++$q while $idx[$p-1] > $idx[$q];
                            @idx[$p-1,$q]=@idx[$q,$p-1];
                    }
            }

            permute { print "@_\n" } split;

    The "Algorithm::Loops" module also provides the "NextPermute" and
    "NextPermuteNum" functions which efficiently find all unique
    permutations of an array, even if it contains duplicate values,
    modifying it in-place: if its elements are in reverse-sorted order then
    the array is reversed, making it sorted, and it returns false; otherwise
    the next permutation is returned.

    "NextPermute" uses string order and "NextPermuteNum" numeric order, so
    you can enumerate all the permutations of 0..9 like this:

            use Algorithm::Loops qw(NextPermuteNum);

        my @list= 0..9;
        do { print "@list\n" } while NextPermuteNum @list;



--------------------------------------------------------------------

The perlfaq-workers, a group of volunteers, maintain the perlfaq. They
are not necessarily experts in every domain where Perl might show up,
so please include as much information as possible and relevant in any
corrections. The perlfaq-workers also don't have access to every
operating system or platform, so please include relevant details for
corrections to examples that do not work on particular platforms.
Working code is greatly appreciated.

If you'd like to help maintain the perlfaq, see the details in 
perlfaq.pod.


------------------------------

Date: Fri, 02 Oct 2009 16:00:02 GMT
From: PerlFAQ Server <brian@theperlreview.com>
Subject: FAQ 5.14 How can I translate tildes (~) in a filename?
Message-Id: <6spxm.47240$j34.27274@newsfe01.iad>

This is an excerpt from the latest version perlfaq5.pod, which
comes with the standard Perl distribution. These postings aim to 
reduce the number of repeated questions as well as allow the community
to review and update the answers. The latest version of the complete
perlfaq is at http://faq.perl.org .

--------------------------------------------------------------------

5.14: How can I translate tildes (~) in a filename?

    Use the <> ("glob()") operator, documented in perlfunc. Versions of Perl
    older than 5.6 require that you have a shell installed that groks
    tildes. Later versions of Perl have this feature built in. The
    "File::KGlob" module (available from CPAN) gives more portable glob
    functionality.

    Within Perl, you may use this directly:

            $filename =~ s{
              ^ ~             # find a leading tilde
              (               # save this in $1
                  [^/]        # a non-slash character
                        *     # repeated 0 or more times (0 means me)
              )
            }{
              $1
                  ? (getpwnam($1))[7]
                  : ( $ENV{HOME} || $ENV{LOGDIR} )
            }ex;



--------------------------------------------------------------------

The perlfaq-workers, a group of volunteers, maintain the perlfaq. They
are not necessarily experts in every domain where Perl might show up,
so please include as much information as possible and relevant in any
corrections. The perlfaq-workers also don't have access to every
operating system or platform, so please include relevant details for
corrections to examples that do not work on particular platforms.
Working code is greatly appreciated.

If you'd like to help maintain the perlfaq, see the details in 
perlfaq.pod.


------------------------------

Date: Fri, 02 Oct 2009 21:59:55 GMT
From: PerlFAQ Server <brian@theperlreview.com>
Subject: FAQ 9.23 How do I find out my hostname, domainname, or IP address?
Message-Id: <vJuxm.17652$kC.7013@newsfe11.iad>

This is an excerpt from the latest version perlfaq9.pod, which
comes with the standard Perl distribution. These postings aim to 
reduce the number of repeated questions as well as allow the community
to review and update the answers. The latest version of the complete
perlfaq is at http://faq.perl.org .

--------------------------------------------------------------------

9.23: How do I find out my hostname, domainname, or IP address?

    (contributed by brian d foy)

    The Net::Domain module, which is part of the standard distribution
    starting in perl5.7.3, can get you the fully qualified domain name
    (FQDN), the host name, or the domain name.

            use Net::Domain qw(hostname hostfqdn hostdomain);

            my $host = hostfqdn();

    The "Sys::Hostname" module, included in the standard distribution since
    perl5.6, can also get the hostname.

            use Sys::Hostname;

            $host = hostname();

    To get the IP address, you can use the "gethostbyname" built-in function
    to turn the name into a number. To turn that number into the dotted
    octet form (a.b.c.d) that most people expect, use the "inet_ntoa"
    function from the <Socket> module, which also comes with perl.

            use Socket;

            my $address = inet_ntoa(
                    scalar gethostbyname( $host || 'localhost' )
                    );



--------------------------------------------------------------------

The perlfaq-workers, a group of volunteers, maintain the perlfaq. They
are not necessarily experts in every domain where Perl might show up,
so please include as much information as possible and relevant in any
corrections. The perlfaq-workers also don't have access to every
operating system or platform, so please include relevant details for
corrections to examples that do not work on particular platforms.
Working code is greatly appreciated.

If you'd like to help maintain the perlfaq, see the details in 
perlfaq.pod.


------------------------------

Date: Fri, 02 Oct 2009 10:43:28 -0700
From: sln@netherlands.com
Subject: Re: machine dependent left shift results
Message-Id: <qtecc5ta43qdskg3gk0uce9fggmu36c6ld@4ax.com>

On Thu, 1 Oct 2009 13:22:10 -0700, "easily_confused" <sorry@nospam.com> wrote:

>On a 32 bit machine, ~0<<32 gives 11111111111111111111111111111111  (I was
>expecting 0)
>
>(~0<<31)<<1 gives 0.
>
And this is correct.

I don't understand what you mean.

~0 << 0  (or just ~0) gives
  11111111111111111111111111111111

~0<<32 gives
  11111111111111111111111111111111

32 bit shifts later you get the same thing. 
Which makes sence.
I'm pretty sure that you only get 0-31 bit shifts
on 32 bit systems.

So that:
  << 32  equals  << 0
  << 33  equals  << 1
  << 34  equals  << 2
  ..
  ..
  << 31  equals  << 31

Therefore
 ~0 << 32  equals ~0 << 0

and
  (~0<<31) << 1 equals 0
  (~0<<31) << 2 equals 0
  (~0<<31) << 3 equals 0
  ..
  ..
  (~0<<31) << 33 equals (~0<<31) << 1 equals 0


This is just my guess. I imagine the pre-processor
rolls 32 back to 0.

-sln
-------------------

use strict;
use warnings;

for (0 .. 35) {
	printf "$_\t  %b \n", ~0<<$_;
}
print "\n";

for (0 .. 35) {
	printf "$_\t  %b \n", 1<<$_;
}
print "\n";

for (0 .. 35) {
	printf "$_\t  %b \n", 4<<$_;
}

__END__

0         11111111111111111111111111111111
1         11111111111111111111111111111110
2         11111111111111111111111111111100
3         11111111111111111111111111111000
4         11111111111111111111111111110000
5         11111111111111111111111111100000
6         11111111111111111111111111000000
7         11111111111111111111111110000000
8         11111111111111111111111100000000
9         11111111111111111111111000000000
10        11111111111111111111110000000000
11        11111111111111111111100000000000
12        11111111111111111111000000000000
13        11111111111111111110000000000000
14        11111111111111111100000000000000
15        11111111111111111000000000000000
16        11111111111111110000000000000000
17        11111111111111100000000000000000
18        11111111111111000000000000000000
19        11111111111110000000000000000000
20        11111111111100000000000000000000
21        11111111111000000000000000000000
22        11111111110000000000000000000000
23        11111111100000000000000000000000
24        11111111000000000000000000000000
25        11111110000000000000000000000000
26        11111100000000000000000000000000
27        11111000000000000000000000000000
28        11110000000000000000000000000000
29        11100000000000000000000000000000
30        11000000000000000000000000000000
31        10000000000000000000000000000000
32        11111111111111111111111111111111
33        11111111111111111111111111111110
34        11111111111111111111111111111100
35        11111111111111111111111111111000

0         1
1         10
2         100
3         1000
4         10000
5         100000
6         1000000
7         10000000
8         100000000
9         1000000000
10        10000000000
11        100000000000
12        1000000000000
13        10000000000000
14        100000000000000
15        1000000000000000
16        10000000000000000
17        100000000000000000
18        1000000000000000000
19        10000000000000000000
20        100000000000000000000
21        1000000000000000000000
22        10000000000000000000000
23        100000000000000000000000
24        1000000000000000000000000
25        10000000000000000000000000
26        100000000000000000000000000
27        1000000000000000000000000000
28        10000000000000000000000000000
29        100000000000000000000000000000
30        1000000000000000000000000000000
31        10000000000000000000000000000000
32        1
33        10
34        100
35        1000

0         100
1         1000
2         10000
3         100000
4         1000000
5         10000000
6         100000000
7         1000000000
8         10000000000
9         100000000000
10        1000000000000
11        10000000000000
12        100000000000000
13        1000000000000000
14        10000000000000000
15        100000000000000000
16        1000000000000000000
17        10000000000000000000
18        100000000000000000000
19        1000000000000000000000
20        10000000000000000000000
21        100000000000000000000000
22        1000000000000000000000000
23        10000000000000000000000000
24        100000000000000000000000000
25        1000000000000000000000000000
26        10000000000000000000000000000
27        100000000000000000000000000000
28        1000000000000000000000000000000
29        10000000000000000000000000000000
30        0
31        0
32        100
33        1000
34        10000
35        100000



------------------------------

Date: Fri, 2 Oct 2009 22:58:48 +0200
From: "Peter J. Holzer" <hjp-usenet2@hjp.at>
Subject: Re: machine dependent left shift results
Message-Id: <slrnhccqc9.q6k.hjp-usenet2@hrunkner.hjp.at>

On 2009-10-02 17:43, sln@netherlands.com <sln@netherlands.com> wrote:
> On Thu, 1 Oct 2009 13:22:10 -0700, "easily_confused" <sorry@nospam.com> wrote:
>>On a 32 bit machine, ~0<<32 gives 11111111111111111111111111111111  (I was
>>expecting 0)
>>
>>(~0<<31)<<1 gives 0.
>>
> And this is correct.
>
> I don't understand what you mean.
>
> ~0 << 0  (or just ~0) gives
>   11111111111111111111111111111111
>
> ~0<<32 gives
>   11111111111111111111111111111111
>
> 32 bit shifts later you get the same thing. 
> Which makes sence.

Mathematically it doesn't make sense.

 (x << y) << z should be same as x << (y + z)

However, from the point of view of a processor designer it does make
sense.

> I'm pretty sure that you only get 0-31 bit shifts
> on 32 bit systems.
>
> So that:
>  << 32  equals  << 0
>  << 33  equals  << 1
>  << 34  equals  << 2
>   ..
>   ..
>  << 31  equals  << 31
[...]
> This is just my guess. I imagine the pre-processor
> rolls 32 back to 0.

Actually, it's the processor. x86 type CPUs (since the 386 or 486, IIRC)
use a so-called barrel shifter to shift by arbitrary amounts in a single
cycle. To keep that shifter at a reasonable size (by 1980's standards of
processor design) it uses only the lower 5 bits of shift width and
ignores the rest.

	hp


------------------------------

Date: Fri, 2 Oct 2009 21:18:08 +0200
From: Martijn Lievaart <m@rtij.nl.invlalid>
Subject: Re: open() close() same file many times
Message-Id: <g80ip6-i3c.ln1@news.rtij.nl>

On Fri, 02 Oct 2009 04:41:49 -0700, alfonsobaldaserra wrote:

> hello list
> 
> i am writing a script to check memory usage on linux.
> 
> the script opens and closes /proc/meminfo 5 times in 5 seconds to
> calculate memory usage on 5 seconds average, it goes something like
> 
> for (1..5) {
>   open MEM, "/proc/meminfo" or die "..." while (<MEM>) {
>     ...
>   }
>   close MEM;
>   sleep 1;
> }
> 
> i was just wondering if this is advisable to open/close file that fast? 
> is there any better approach to do this?

Juergen already pointed out that you could use seek(), but I would add, 
does it really matter? This is all in memory stuff and unless it runs on 
a severely handicapped machine (embedded processors can be seriously 
under powered) you probably won't even be able to measure the difference.

Just my E 0.02

M4


------------------------------

Date: Fri, 02 Oct 2009 10:43:50 -0700
From: HASM <netnews@invalid.com>
Subject: Re: simple hash
Message-Id: <m3ljjtsnc9.fsf@127.0.0.1>

"Uri Guttman" <uri@StemSystems.com> writes:

> also don't name a scalar and hash with such similar names. the hash
> would be better named %year_cnt or something like that.

I do this all the time.  Once you get the hang of it, it makes naming stuff
a lot easier.  Agreed it may confuse things a bit,

-- HASM


------------------------------

Date: Fri, 2 Oct 2009 08:53:16 -0700 (PDT)
From: ccc31807 <cartercc@gmail.com>
Subject: Re: sort function warning, variable will not stay shared
Message-Id: <cba296b7-6c5f-4052-8398-4ef7b297e8ff@z24g2000yqb.googlegroups.com>

On Oct 2, 10:58=A0am, Tad J McClellan <ta...@seesig.invalid> wrote:
> Does it contain names like
>
> =A0 =A0 George Forman Jr
> =A0 =A0 Susan Saint James
> =A0 =A0 Kim Jong Il

No. The data is validated and will always match /^(\w+) (\w+)$/.

Yeah, I am aware of constructs like O'Reilly, St. Cyr, de Ruyter,
etc., but these are handled by another routine (that works without
warnings). This particular table contains temporary values that users
will later edit. The important value is username, which is a
guaranteed unique value, and all the name does is cue the user. After
the user edits his name, the name value disappears forever.

CC


------------------------------

Date: Fri, 2 Oct 2009 18:28:21 +0100
From: Ben Morrow <ben@morrow.me.uk>
Subject: Re: sort function warning, variable will not stay shared
Message-Id: <lqphp6-unj1.ln1@osiris.mauzo.dyndns.org>


Quoth ccc31807 <cartercc@gmail.com>:
> 
> This is the code I use to iterate through the hash:
> foreach my $key (sort sortf keys %{$content})
> {
>   #print values here, like
>   $content->{$key}{'name'}
>   $content->{$key}{'status'}
>   $content->{$key}{'username'}
>   $content->{$key}{'role'}
> }
> 
> Here is the sortf function, which is an inner subroutine in the block
> containing the hash iteration:

This is your mistake. Placing a sub inside another sub (or a top-level
loop, for that matter) is always wrong. The technical reason for this is
that named subs are not closures in Perl 5: in simple terms, the
*second* time you run the block of code that does the sort the sub will
still be looking at the $content variable from the *first* time, and you
will get incorrect results.

There are two solutions: use an anonymous sub instead, since anon subs
*are* closures, or pass sort a block instead of a sub, which compiles
the block as an anon sub.

    my $sortf = sub { ... }
    for my $key (sort $sortf keys %$content) {
        ...
    }

    for my $key (
        sort {
            ...
        } keys %$content
    ){
        ...
    }

Ben



------------------------------

Date: Fri, 2 Oct 2009 13:06:17 -0700 (PDT)
From: ccc31807 <cartercc@gmail.com>
Subject: Re: sort function warning, variable will not stay shared
Message-Id: <0ab45915-abda-43c5-aa25-2dd9b3ca9b2b@l2g2000yqd.googlegroups.com>

On Oct 2, 1:28=A0pm, Ben Morrow <b...@morrow.me.uk> wrote:
> There are two solutions: use an anonymous sub instead, since anon subs
> *are* closures, or pass sort a block instead of a sub, which compiles
> the block as an anon sub.

Thanks, Ben. I moved the code in the block to the sort function, and
it works without generating warnings.

Actually, this occurred to me earlier, but I couldn't quite wrap my
mind around declaring lexical variables in the sort block. Now that I
see it, it looks (almost) normal.

I would like to make this observation -- Learning how to sort on the
various elements of a multi-level data structure isn't obvious, and
isn't particularly easy, and the know-how probably isn't that common,
but it's a very useful thing to learn. I'm not real good at it, but
I've figured out the basics enough to do what I need to do. We
occasionally have code walk-throughs with people who don't use Perl
(I'm essentially the only Perl guy in the shop) and I've learned to
expect and appreciate the WTF reaction every time we hit the unwinding
of a multi-level hash, with the sort block a little extra piece of
lunacy. It's nice being able to see order in what everyone else
perceives as chaos.

CC


------------------------------

Date: Fri, 02 Oct 2009 16:44:49 -0400
From: "Uri Guttman" <uri@StemSystems.com>
Subject: Re: sort function warning, variable will not stay shared
Message-Id: <87iqex34qm.fsf@quad.sysarch.com>

>>>>> "c" == ccc31807  <cartercc@gmail.com> writes:

  c> I would like to make this observation -- Learning how to sort on
  c> the various elements of a multi-level data structure isn't obvious,
  c> and isn't particularly easy, and the know-how probably isn't that
  c> common, but it's a very useful thing to learn. I'm not real good at
  c> it, but I've figured out the basics enough to do what I need to
  c> do. We occasionally have code walk-throughs with people who don't
  c> use Perl (I'm essentially the only Perl guy in the shop) and I've
  c> learned to expect and appreciate the WTF reaction every time we hit
  c> the unwinding of a multi-level hash, with the sort block a little
  c> extra piece of lunacy. It's nice being able to see order in what
  c> everyone else perceives as chaos.

try Sort::Maker and see how it generates sorts. you can print out
generated source and cut/paste it into your code. it is much easier to
define how to get and compare keys in its syntax than the basic sort
when you do multilevel and complex key extraction. also it can generate
sorts in 4 styles including plain (which you did) and the fastest one
GRT.

the issue about accessing the hash ref from inside the sorter is still
a problem but you could eval the generated code in the current
context and it should have access to any lexicals. not tested yet.

uri

-- 
Uri Guttman  ------  uri@stemsystems.com  --------  http://www.sysarch.com --
-----  Perl Code Review , Architecture, Development, Training, Support ------
---------  Gourmet Hot Cocoa Mix  ----  http://bestfriendscocoa.com ---------


------------------------------

Date: Fri, 02 Oct 2009 19:35:28 -0700
From: merlyn@stonehenge.com (Randal L. Schwartz)
Subject: Re: sort function warning, variable will not stay shared
Message-Id: <86iqexyzkf.fsf@blue.stonehenge.com>

>>>>> "Ben" == Ben Morrow <ben@morrow.me.uk> writes:

Ben>  The technical reason for this is
Ben> that named subs are not closures in Perl 5:

You have "not" in there, where I think you meant "named subs *are* closures",
because you correctly describe the effect of it being a closure here:

Ben>  in simple terms, the
Ben> *second* time you run the block of code that does the sort the sub will
Ben> still be looking at the $content variable from the *first* time, and you
Ben> will get incorrect results.

As in, the variables get the closure treatment the first time, and therefore
they are no longer "shared".

-- 
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion


------------------------------

Date: Fri, 2 Oct 2009 09:48:57 -0700 (PDT)
From: Stefan <s1037989@gmail.com>
Subject: Re: Web-based two-column diff with color
Message-Id: <a8e54cd9-5ab4-4858-a938-561a39c026f5@m11g2000yqf.googlegroups.com>

Thanks for the feedback Tad and sln!  :)


------------------------------

Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin) 
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>


Administrivia:

To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.

Back issues are available via anonymous ftp from
ftp://cil-www.oce.orst.edu/pub/perl/old-digests. 

#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.


------------------------------
End of Perl-Users Digest V11 Issue 2620
***************************************


home help back first fref pref prev next nref lref last post