Hello community,
here is the log from the commit of package perl-Scalar-List-Utils for
openSUSE:Factory checked in at 2016-04-12 19:33:54
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/perl-Scalar-List-Utils (Old)
and /work/SRC/openSUSE:Factory/.perl-Scalar-List-Utils.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "perl-Scalar-List-Utils"
Changes:
--------
---
/work/SRC/openSUSE:Factory/perl-Scalar-List-Utils/perl-Scalar-List-Utils.changes
2016-03-26 15:27:37.000000000 +0100
+++
/work/SRC/openSUSE:Factory/.perl-Scalar-List-Utils.new/perl-Scalar-List-Utils.changes
2016-04-12 19:33:55.000000000 +0200
@@ -1,0 +2,16 @@
+Mon Apr 4 10:21:07 UTC 2016 - [email protected]
+
+- updated to 1.45
+ see /usr/share/doc/packages/perl-Scalar-List-Utils/Changes
+
+ 1.45 -- 2016/03/25 16:09:40
+ [CHANGES]
+ * Renamed existing uniq() to uniqstr()
+ * Canonicalise undef to {empty string,zero} in uniq{str,num}()
+ * Add a new uniq() with more DWIMish semantics around undef
+
+ [BUGFIXES]
+ * Fix uses of GET magic by the uniq*() family of functions. GET magic
+ is now always invoked exactly once if it exists.
+
+-------------------------------------------------------------------
Old:
----
Scalar-List-Utils-1.44.tar.gz
New:
----
Scalar-List-Utils-1.45.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ perl-Scalar-List-Utils.spec ++++++
--- /var/tmp/diff_new_pack.lKx4tA/_old 2016-04-12 19:33:55.000000000 +0200
+++ /var/tmp/diff_new_pack.lKx4tA/_new 2016-04-12 19:33:55.000000000 +0200
@@ -17,7 +17,7 @@
Name: perl-Scalar-List-Utils
-Version: 1.44
+Version: 1.45
Release: 0
%define cpan_name Scalar-List-Utils
Summary: Common Scalar and List utility subroutines
++++++ Scalar-List-Utils-1.44.tar.gz -> Scalar-List-Utils-1.45.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Scalar-List-Utils-1.44/Changes
new/Scalar-List-Utils-1.45/Changes
--- old/Scalar-List-Utils-1.44/Changes 2016-03-18 00:09:46.000000000 +0100
+++ new/Scalar-List-Utils-1.45/Changes 2016-03-25 17:09:57.000000000 +0100
@@ -1,3 +1,13 @@
+1.45 -- 2016/03/25 16:09:40
+ [CHANGES]
+ * Renamed existing uniq() to uniqstr()
+ * Canonicalise undef to {empty string,zero} in uniq{str,num}()
+ * Add a new uniq() with more DWIMish semantics around undef
+
+ [BUGFIXES]
+ * Fix uses of GET magic by the uniq*() family of functions. GET magic
+ is now always invoked exactly once if it exists.
+
1.44 -- 2016/03/17 23:08:46
[CHANGES]
* Added List::Util::uniq() and uniqnum()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Scalar-List-Utils-1.44/ListUtil.xs
new/Scalar-List-Utils-1.45/ListUtil.xs
--- old/Scalar-List-Utils-1.44/ListUtil.xs 2016-03-18 00:07:44.000000000
+0100
+++ new/Scalar-List-Utils-1.45/ListUtil.xs 2016-03-23 19:20:15.000000000
+0100
@@ -1011,8 +1011,9 @@
uniq(...)
PROTOTYPE: @
ALIAS:
- uniq = 0
- uniqnum = 1
+ uniqnum = 0
+ uniqstr = 1
+ uniq = 2
CODE:
{
int retcount = 0;
@@ -1020,28 +1021,33 @@
SV **args = &PL_stack_base[ax];
HV *seen;
- if(items < 2) {
+ if(items == 0 || (items == 1 && !SvGAMAGIC(args[0]) && SvOK(args[0]))) {
+ /* Optimise for the case of the empty list or a defined nonmagic
+ * singleton. Leave a singleton magical||undef for the regular case */
retcount = items;
goto finish;
}
sv_2mortal((SV *)(seen = newHV()));
- if(ix) {
+ if(ix == 0) {
+ /* uniqnum */
/* A temporary buffer for number stringification */
SV *keysv = sv_newmortal();
for(index = 0 ; index < items ; index++) {
SV *arg = args[index];
- SvGETMAGIC(arg);
+ if(SvGAMAGIC(arg))
+ /* clone the value so we don't invoke magic again */
+ arg = sv_mortalcopy(arg);
if(SvUOK(arg))
- sv_setpvf(keysv, "%"UVuf, SvUV_nomg(arg));
+ sv_setpvf(keysv, "%"UVuf, SvUV(arg));
else if(SvIOK(arg))
- sv_setpvf(keysv, "%"IVdf, SvIV_nomg(arg));
+ sv_setpvf(keysv, "%"IVdf, SvIV(arg));
else
- sv_setpvf(keysv, "%"NVgf, SvNV_nomg(arg));
+ sv_setpvf(keysv, "%"NVgf, SvNV(arg));
#ifdef HV_FETCH_EMPTY_HE
HE* he = hv_common(seen, NULL, SvPVX(keysv), SvCUR(keysv), 0,
HV_FETCH_LVALUE | HV_FETCH_EMPTY_HE, NULL, 0);
if (HeVAL(he))
@@ -1056,29 +1062,51 @@
#endif
if(GIMME_V == G_ARRAY)
- ST(retcount) = arg;
+ ST(retcount) = SvOK(arg) ? arg : sv_2mortal(newSViv(0));
retcount++;
}
}
- else
+ else {
+ /* uniqstr or uniq */
+ int seen_undef = 0;
+
for(index = 0 ; index < items ; index++) {
+ SV *arg = args[index];
+
+ if(SvGAMAGIC(arg))
+ /* clone the value so we don't invoke magic again */
+ arg = sv_mortalcopy(arg);
+
+ if(ix == 2 && !SvOK(arg)) {
+ /* special handling of undef for uniq() */
+ if(seen_undef)
+ continue;
+
+ seen_undef++;
+
+ if(GIMME_V == G_ARRAY)
+ ST(retcount) = arg;
+ retcount++;
+ continue;
+ }
#ifdef HV_FETCH_EMPTY_HE
- HE* he = hv_common(seen, args[index], NULL, 0, 0, HV_FETCH_LVALUE
| HV_FETCH_EMPTY_HE, NULL, 0);
+ HE* he = hv_common(seen, arg, NULL, 0, 0, HV_FETCH_LVALUE |
HV_FETCH_EMPTY_HE, NULL, 0);
if (HeVAL(he))
continue;
HeVAL(he) = &PL_sv_undef;
#else
- if (hv_exists_ent(seen, args[index], 0))
+ if (hv_exists_ent(seen, arg, 0))
continue;
- hv_store_ent(seen, args[index], &PL_sv_undef, 0);
+ hv_store_ent(seen, arg, &PL_sv_undef, 0);
#endif
if(GIMME_V == G_ARRAY)
- ST(retcount) = args[index];
+ ST(retcount) = SvOK(arg) ? arg : sv_2mortal(newSVpvn("", 0));
retcount++;
}
+ }
finish:
if(GIMME_V == G_ARRAY)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Scalar-List-Utils-1.44/META.json
new/Scalar-List-Utils-1.45/META.json
--- old/Scalar-List-Utils-1.44/META.json 2016-03-18 00:10:20.000000000
+0100
+++ new/Scalar-List-Utils-1.45/META.json 2016-03-25 17:14:35.000000000
+0100
@@ -49,6 +49,6 @@
"web" : "https://github.com/Scalar-List-Utils/Scalar-List-Utils"
}
},
- "version" : "1.44",
+ "version" : "1.45",
"x_serialization_backend" : "JSON::PP version 2.27300"
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Scalar-List-Utils-1.44/META.yml
new/Scalar-List-Utils-1.45/META.yml
--- old/Scalar-List-Utils-1.44/META.yml 2016-03-18 00:10:20.000000000 +0100
+++ new/Scalar-List-Utils-1.45/META.yml 2016-03-25 17:14:35.000000000 +0100
@@ -23,5 +23,5 @@
resources:
bugtracker:
https://rt.cpan.org/Public/Dist/Display.html?Name=Scalar-List-Utils
repository: https://github.com/Scalar-List-Utils/Scalar-List-Utils.git
-version: '1.44'
+version: '1.45'
x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Scalar-List-Utils-1.44/lib/List/Util/XS.pm
new/Scalar-List-Utils-1.45/lib/List/Util/XS.pm
--- old/Scalar-List-Utils-1.44/lib/List/Util/XS.pm 2016-03-18
00:09:51.000000000 +0100
+++ new/Scalar-List-Utils-1.45/lib/List/Util/XS.pm 2016-03-25
17:14:00.000000000 +0100
@@ -3,7 +3,7 @@
use warnings;
use List::Util;
-our $VERSION = "1.44"; # FIXUP
+our $VERSION = "1.45"; # FIXUP
$VERSION = eval $VERSION; # FIXUP
1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Scalar-List-Utils-1.44/lib/List/Util.pm
new/Scalar-List-Utils-1.45/lib/List/Util.pm
--- old/Scalar-List-Utils-1.44/lib/List/Util.pm 2016-03-18 00:09:51.000000000
+0100
+++ new/Scalar-List-Utils-1.45/lib/List/Util.pm 2016-03-25 17:14:00.000000000
+0100
@@ -12,10 +12,10 @@
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(
- all any first min max minstr maxstr none notall product reduce sum sum0
shuffle uniq uniqnum
+ all any first min max minstr maxstr none notall product reduce sum sum0
shuffle uniq uniqnum uniqstr
pairs unpairs pairkeys pairvalues pairmap pairgrep pairfirst
);
-our $VERSION = "1.44";
+our $VERSION = "1.45";
our $XS_VERSION = $VERSION;
$VERSION = eval $VERSION;
@@ -52,7 +52,7 @@
pairs pairkeys pairvalues pairfirst pairgrep pairmap
- shuffle
+ shuffle uniqnum uniqstr
);
=head1 DESCRIPTION
@@ -114,6 +114,20 @@
$foo = reduce { $a + $b } 0, @values; # sum with 0 identity value
+The above example code blocks also suggest how to use C<reduce> to build a
+more efficient combined version of one of these basic functions and a C<map>
+block. For example, to find the total length of the all the strings in a list,
+we could use
+
+ $total = sum map { length } @strings;
+
+However, this produces a list of temporary integer values as long as the
+original list of strings, only to reduce it down to a single value again. We
+can compute the same result more efficiently by using C<reduce> with a code
+block that accumulates lengths by writing this instead as:
+
+ $total = reduce { $a + length $b } 0, @strings
+
The remaining list-reduction functions are all specialisations of this generic
idea.
@@ -466,31 +480,64 @@
my @subset = uniq @values
+I<Since version 1.45.>
+
Filters a list of values to remove subsequent duplicates, as judged by a
-string equality test. Preserves the order of unique elements, and retains the
-first value of any duplicate set.
+DWIM-ish string equality or C<undef> test. Preserves the order of unique
+elements, and retains the first value of any duplicate set.
my $count = uniq @values
In scalar context, returns the number of elements that would have been
returned as a list.
-Note that C<undef> is not handled specially; it is treated the same as most
-other perl operations that work on strings. That is, C<undef> behaves
-identically to the empty string, but in addition a warning is produced.
+The C<undef> value is treated by this function as distinct from the empty
+string, and no warning will be produced. It is left as-is in the returned
+list. Subsequent C<undef> values are still considered identical to the first,
+and will be removed.
=head2 uniqnum
my @subset = uniqnum @values
-Filters a list of values similarly to L</uniq>, but judges duplicates
-numerically instead.
+I<Since version 1.44.>
+
+Filters a list of values to remove subsequent duplicates, as judged by a
+numerical equality test. Preserves the order of unique elements, and retains
+the first value of any duplicate set.
my $count = uniqnum @values
In scalar context, returns the number of elements that would have been
returned as a list.
+Note that C<undef> is treated much as other numerical operations treat it; it
+compares equal to zero but additionally produces a warning if such warnings
+are enabled (C<use warnings 'uninitialized';>). In addition, an C<undef> in
+the returned list is coerced into a numerical zero, so that the entire list of
+values returned by C<uniqnum> are well-behaved as numbers.
+
+=head2 uniqstr
+
+ my @subset = uniqstr @values
+
+I<Since version 1.45.>
+
+Filters a list of values to remove subsequent duplicates, as judged by a
+string equality test. Preserves the order of unique elements, and retains the
+first value of any duplicate set.
+
+ my $count = uniqstr @values
+
+In scalar context, returns the number of elements that would have been
+returned as a list.
+
+Note that C<undef> is treated much as other string operations treat it; it
+compares equal to the empty string but additionally produces a warning if such
+warnings are enabled (C<use warnings 'uninitialized';>). In addition, an
+C<undef> in the returned list is coerced into an empty string, so that the
+entire list of values returned by C<uniqstr> are well-behaved as strings.
+
=cut
=head1 KNOWN BUGS
@@ -550,17 +597,9 @@
say for uniqnum( $x, $y );
Will print just the value of C<$x>, believing that C<$y> is a numerically-
-equivalent value. This bug does not affect C<uniq()>, which will correctly
+equivalent value. This bug does not affect C<uniqstr()>, which will correctly
observe that the two values stringify to different strings.
-=head2 uniqnum() invokes GET magic multiple times before perl 5.14
-
-Perl versions before 5.14 lack the C<SvNV_nomg()> and related macros. On these
-older versions, C<uniqnum()> will invoke GET magic twice on each argument
-passed in. This ought not cause any major problems other than a slight
-performance penalty, because well-designed GET magic should be idempotent.
-This does not affect C<uniq()>, nor builds for perl 5.14 or later.
-
=head1 SUGGESTED ADDITIONS
The following are additions that have been requested, but I have been reluctant
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Scalar-List-Utils-1.44/lib/Scalar/Util.pm
new/Scalar-List-Utils-1.45/lib/Scalar/Util.pm
--- old/Scalar-List-Utils-1.44/lib/Scalar/Util.pm 2016-03-18
00:09:51.000000000 +0100
+++ new/Scalar-List-Utils-1.45/lib/Scalar/Util.pm 2016-03-25
17:14:00.000000000 +0100
@@ -17,7 +17,7 @@
dualvar isdual isvstring looks_like_number openhandle readonly set_prototype
tainted
);
-our $VERSION = "1.44";
+our $VERSION = "1.45";
$VERSION = eval $VERSION;
require List::Util; # List::Util loads the XS
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Scalar-List-Utils-1.44/lib/Sub/Util.pm
new/Scalar-List-Utils-1.45/lib/Sub/Util.pm
--- old/Scalar-List-Utils-1.44/lib/Sub/Util.pm 2016-03-18 00:09:51.000000000
+0100
+++ new/Scalar-List-Utils-1.45/lib/Sub/Util.pm 2016-03-25 17:14:00.000000000
+0100
@@ -15,7 +15,7 @@
subname set_subname
);
-our $VERSION = "1.44";
+our $VERSION = "1.45";
$VERSION = eval $VERSION;
require List::Util; # as it has the XS
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Scalar-List-Utils-1.44/t/uniq.t
new/Scalar-List-Utils-1.45/t/uniq.t
--- old/Scalar-List-Utils-1.44/t/uniq.t 2016-03-18 00:09:51.000000000 +0100
+++ new/Scalar-List-Utils-1.45/t/uniq.t 2016-03-25 17:14:00.000000000 +0100
@@ -3,28 +3,45 @@
use strict;
use warnings;
-use Test::More tests => 19;
-use List::Util qw( uniq uniqnum );
+use Test::More tests => 30;
+use List::Util qw( uniqnum uniqstr uniq );
-is_deeply( [ uniq ],
+use Tie::Array;
+
+is_deeply( [ uniqstr ],
[],
- 'uniq of empty list' );
+ 'uniqstr of empty list' );
-is_deeply( [ uniq qw( abc ) ],
+is_deeply( [ uniqstr qw( abc ) ],
[qw( abc )],
- 'uniq of singleton list' );
+ 'uniqstr of singleton list' );
-is_deeply( [ uniq qw( x x x ) ],
+is_deeply( [ uniqstr qw( x x x ) ],
[qw( x )],
- 'uniq of repeated-element list' );
+ 'uniqstr of repeated-element list' );
-is_deeply( [ uniq qw( a b a c ) ],
+is_deeply( [ uniqstr qw( a b a c ) ],
[qw( a b c )],
- 'uniq removes subsequent duplicates' );
+ 'uniqstr removes subsequent duplicates' );
-is_deeply( [ uniq qw( 1 1.0 1E0 ) ],
+is_deeply( [ uniqstr qw( 1 1.0 1E0 ) ],
[qw( 1 1.0 1E0 )],
- 'uniq compares strings' );
+ 'uniqstr compares strings' );
+
+{
+ my $warnings = "";
+ local $SIG{__WARN__} = sub { $warnings .= join "", @_ };
+
+ is_deeply( [ uniqstr "", undef ],
+ [ "" ],
+ 'uniqstr considers undef and empty-string equivalent' );
+
+ ok( length $warnings, 'uniqstr on undef yields a warning' );
+
+ is_deeply( [ uniqstr undef ],
+ [ "" ],
+ 'uniqstr on undef coerces to empty-string' );
+}
{
my $warnings = "";
@@ -32,15 +49,15 @@
my $cafe = "cafe\x{301}";
- is_deeply( [ uniq $cafe ],
+ is_deeply( [ uniqstr $cafe ],
[ $cafe ],
- 'uniq is happy with Unicode strings' );
+ 'uniqstr is happy with Unicode strings' );
utf8::encode( my $cafebytes = $cafe );
- is_deeply( [ uniq $cafe, $cafebytes ],
+ is_deeply( [ uniqstr $cafe, $cafebytes ],
[ $cafe, $cafebytes ],
- 'uniq does not squash bytewise-equal but differently-encoded
strings' );
+ 'uniqstr does not squash bytewise-equal but differently-encoded
strings' );
is( $warnings, "", 'No warnings are printed when handling Unicode strings'
);
}
@@ -70,7 +87,41 @@
'uniqnum preserves uniqness of full integer range' );
}
-is( scalar( uniq qw( a b c d a b e ) ), 5, 'uniq() in scalar context' );
+{
+ my $warnings = "";
+ local $SIG{__WARN__} = sub { $warnings .= join "", @_ };
+
+ is_deeply( [ uniqnum 0, undef ],
+ [ 0 ],
+ 'uniqnum considers undef and zero equivalent' );
+
+ ok( length $warnings, 'uniqnum on undef yields a warning' );
+
+ is_deeply( [ uniqnum undef ],
+ [ 0 ],
+ 'uniqnum on undef coerces to zero' );
+}
+
+is_deeply( [ uniq () ],
+ [],
+ 'uniq of empty list' );
+
+{
+ my $warnings = "";
+ local $SIG{__WARN__} = sub { $warnings .= join "", @_ };
+
+ is_deeply( [ uniq "", undef ],
+ [ "", undef ],
+ 'uniq distintinguishes empty-string from undef' );
+
+ is_deeply( [ uniq undef, undef ],
+ [ undef ],
+ 'uniq considers duplicate undefs as identical' );
+
+ ok( !length $warnings, 'uniq on undef does not warn' );
+}
+
+is( scalar( uniqstr qw( a b c d a b e ) ), 5, 'uniqstr() in scalar context' );
{
package Stringify;
@@ -83,9 +134,9 @@
my @strs = map { Stringify->new( $_ ) } qw( foo foo bar );
- is_deeply( [ uniq @strs ],
+ is_deeply( [ uniqstr @strs ],
[ $strs[0], $strs[2] ],
- 'uniq respects stringify overload' );
+ 'uniqstr respects stringify overload' );
}
{
@@ -122,25 +173,41 @@
my @destroyed = (0) x 3;
my @notifiers = map { DestroyNotifier->new( \$destroyed[$_] ) } 0 .. 2;
- my @uniq = uniq @notifiers;
+ my @uniqstr = uniqstr @notifiers;
undef @notifiers;
is_deeply( \@destroyed, [ 0, 1, 1 ],
- 'values filtered by uniq() are destroyed' );
+ 'values filtered by uniqstr() are destroyed' );
- undef @uniq;
+ undef @uniqstr;
is_deeply( \@destroyed, [ 1, 1, 1 ],
'all values destroyed' );
}
{
"a a b" =~ m/(.) (.) (.)/;
- is_deeply( [ uniq $1, $2, $3 ],
+ is_deeply( [ uniqstr $1, $2, $3 ],
[qw( a b )],
- 'uniq handles magic' );
+ 'uniqstr handles magic' );
"1 1 2" =~ m/(.) (.) (.)/;
is_deeply( [ uniqnum $1, $2, $3 ],
[ 1, 2 ],
'uniqnum handles magic' );
}
+
+{
+ my @array;
+ tie @array, 'Tie::StdArray';
+ @array = (
+ ( map { ( 1 .. 10 ) } 0 .. 1 ),
+ ( map { ( 'a' .. 'z' ) } 0 .. 1 )
+ );
+
+ my @u = uniq @array;
+ is_deeply(
+ \@u,
+ [ 1 .. 10, 'a' .. 'z' ],
+ 'uniq uniquifies mixed numbers and strings correctly in a tied array'
+ );
+}