X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2Fsort.pm;h=922f82b46915b1e39bae61558d594afb5da182e2;hb=4c38808d92b95edd5d3bf512019007a1e4a385d9;hp=e785003f4f8fc5384dc0d045b0225efbe3ca3321;hpb=7a8ff2dd4a456a3d3ba44383dd89457f1618ec20;p=p5sagit%2Fp5-mst-13.2.git diff --git a/lib/sort.pm b/lib/sort.pm index e785003..922f82b 100644 --- a/lib/sort.pm +++ b/lib/sort.pm @@ -1,13 +1,9 @@ package sort; -our $VERSION = '1.02'; +our $VERSION = '2.01'; -# Currently the hints for pp_sort are stored in the global variable -# $sort::hints. An improvement would be to store them in $^H{SORT} and have -# this information available somewhere in the listop OP_SORT, to allow lexical -# scoping of this pragma. -- rgs 2002-04-30 - -our $hints = 0; +# The hints for pp_sort are now stored in $^H{sort}; older versions +# of perl used the global variable $sort::hints. -- rjh 2005-12-19 $sort::quicksort_bit = 0x00000001; $sort::mergesort_bit = 0x00000002; @@ -23,18 +19,18 @@ sub import { Carp::croak("sort pragma requires arguments"); } local $_; - no warnings 'uninitialized'; # bitops would warn + $^H{sort} //= 0; while ($_ = shift(@_)) { if (/^_q(?:uick)?sort$/) { - $hints &= ~$sort::sort_bits; - $hints |= $sort::quicksort_bit; + $^H{sort} &= ~$sort::sort_bits; + $^H{sort} |= $sort::quicksort_bit; } elsif ($_ eq '_mergesort') { - $hints &= ~$sort::sort_bits; - $hints |= $sort::mergesort_bit; + $^H{sort} &= ~$sort::sort_bits; + $^H{sort} |= $sort::mergesort_bit; } elsif ($_ eq 'stable') { - $hints |= $sort::stable_bit; + $^H{sort} |= $sort::stable_bit; } elsif ($_ eq 'defaults') { - $hints = 0; + $^H{sort} = 0; } else { require Carp; Carp::croak("sort: unknown subpragma '$_'"); @@ -52,11 +48,11 @@ sub unimport { no warnings 'uninitialized'; # bitops would warn while ($_ = shift(@_)) { if (/^_q(?:uick)?sort$/) { - $hints &= ~$sort::sort_bits; + $^H{sort} &= ~$sort::sort_bits; } elsif ($_ eq '_mergesort') { - $hints &= ~$sort::sort_bits; + $^H{sort} &= ~$sort::sort_bits; } elsif ($_ eq 'stable') { - $hints &= ~$sort::stable_bit; + $^H{sort} &= ~$sort::stable_bit; } else { require Carp; Carp::croak("sort: unknown subpragma '$_'"); @@ -66,10 +62,10 @@ sub unimport { sub current { my @sort; - if ($hints) { - push @sort, 'quicksort' if $hints & $sort::quicksort_bit; - push @sort, 'mergesort' if $hints & $sort::mergesort_bit; - push @sort, 'stable' if $hints & $sort::stable_bit; + if ($^H{sort}) { + push @sort, 'quicksort' if $^H{sort} & $sort::quicksort_bit; + push @sort, 'mergesort' if $^H{sort} & $sort::mergesort_bit; + push @sort, 'stable' if $^H{sort} & $sort::stable_bit; } push @sort, 'mergesort' unless @sort; join(' ', @sort); @@ -92,7 +88,10 @@ sort - perl pragma to control sort() behaviour use sort '_qsort'; # alias for quicksort - my $current = sort::current(); # identify prevailing algorithm + my $current; + BEGIN { + $current = sort::current(); # identify prevailing algorithm + } =head1 DESCRIPTION @@ -152,50 +151,46 @@ have exactly the same effect, leaving the choice of sort algorithm open. =head1 CAVEATS -This pragma is not lexically scoped: its effect is global to the program -it appears in. That means the following will probably not do what you -expect, because I pragmas take effect at compile time, before -I C happens. +As of Perl 5.10, this pragma is lexically scoped and takes effect +at compile time. In earlier versions its effect was global and took +effect at run-time; the documentation suggested using C to +change the behaviour: - { use sort "_quicksort"; + { eval 'use sort qw(defaults _quicksort)'; # force quicksort + eval 'no sort "stable"'; # stability not wanted print sort::current . "\n"; @a = sort @b; + eval 'use sort "defaults"'; # clean up, for others } - { use sort "stable"; + { eval 'use sort qw(defaults stable)'; # force stability print sort::current . "\n"; @c = sort @d; + eval 'use sort "defaults"'; # clean up, for others } - # prints: - # quicksort stable - # quicksort stable - -You can achieve the effect you probably wanted by using C -to defer the pragmas until run time. Use the quoted argument -form of C, I the BLOCK form, as in - eval { use sort "_quicksort" }; # WRONG +Such code no longer has the desired effect, for two reasons. +Firstly, the use of C means that the sorting algorithm +is not changed until runtime, by which time it's too late to +have any effect. Secondly, C is also called at +run-time, when in fact the compile-time value of C +is the one that matters. -or the effect will still be at compile time. -Reset to default options before selecting other subpragmas -(in case somebody carelessly left them on) and after sorting, -as a courtesy to others. +So now this code would be written: - { eval 'use sort qw(defaults _quicksort)'; # force quicksort - eval 'no sort "stable"'; # stability not wanted - print sort::current . "\n"; + { use sort qw(defaults _quicksort); # force quicksort + no sort "stable"; # stability not wanted + my $current; + BEGIN { $current = print sort::current; } + print "$current\n"; @a = sort @b; - eval 'use sort "defaults"'; # clean up, for others + # Pragmas go out of scope at the end of the block } - { eval 'use sort qw(defaults stable)'; # force stability - print sort::current . "\n"; + { use sort qw(defaults stable); # force stability + my $current; + BEGIN { $current = print sort::current; } + print "$current\n"; @c = sort @d; - eval 'use sort "defaults"'; # clean up, for others } - # prints: - # quicksort - # stable - -Scoping for this pragma may change in future versions. =cut