I'm getting a strange behavior from Perl when I try to return
from my sort()
block:
#!/usr/bin/perl
use strict;
use warnings;
my @data = sort {
return &special_sort;
} qw/ 6 1 2 /;
use Data::Dumper;
print STDERR Data::Dumper->Dump([\@data]);
sub special_sort {
# (imagine some custom sorting logic here)
return $a <=> $b;
}
This gives the following messages:
Use of uninitialized value in sort at ./mcve.pl line 6.
Use of uninitialized value in sort at ./mcve.pl line 6.
Use of uninitialized value in sort at ./mcve.pl line 6.
$VAR1 = [
6,
1,
2
];
As you can see, it also failed to sort the list. The odd thing is, the following sort clauses work without any warnings, and sort the data properly:
my @data = sort {
&special_sort;
} qw/ 6 1 2 /;
my @data = sort {
my $res = &special_sort;
return $res;
} qw/ 6 1 2 /;
my @data = sort {
return $a <=> $b;
} qw/ 6 1 2 /;
my @data = sort {
eval { return &special_sort; }
} qw/ 6 1 2 /;
What's going on here? Why do those four work, but the first example doesn't? It shouldn't be the return
statement causing undefined behavior, since two of the working ones have that.
If it turns out the world isn't perfect and I can't (or shouldn't) return
from a block, is there an elegant way to effectively do that?
Edit: It was a bug in Perl. (Note: I did some checking, and I'm slowly figuring out this is down to my confusion between how Perl handles BLOCKs vs. SUBs, hence Question 1. The question is still interesting IMO, and confusing behavior on Perl's part.)
For clarity, I'm using Perl 5.32.0.
Recently, while working on one of the existing SSIS package, we found that there were number of sort blocks in SSIS where as it could have been sorted at the source itself and informing the SSIS package that the data is already sorted at the source and can be processed further.
After performing all these steps, when we created a link between the OLEDB Sources and Merge Join (existing) block, we got the error saying: “ The column with the sortkeyposition value of 1 is not valid. It should be 0 “.
Also, sorting in the SSIS package takes more time as compared to sorting at the source/SQL server for which we may get out of memory exception which will be explained in another blog. So, to fix this issue, we sorted the data at the source using order by statement of SQL as shown:
This is why there is no Sort operator in the first plan, and no Top operator in *either* plan. The underlying problem here is that ORDER BY can serve these two functions - one to determine TOP inclusion, and one to determine presentation order.
This is a bug. A fix has been applied, resolving the issue in upcoming Perl 5.34.
In the meantime, you can replace
return &special_sort;
with
&special_sort; # Avoids the issue.
or
return scalar( &special_sort ); # Force scalar context.
or
return 0+&special_sort; # Force scalar context.
The problem is that special_sort
is incorrectly being called in void context, which is avoided or circumvented by the above workarounds.
I initially claimed that you can't use return
in a sort
block because it's not a sub. I also indicated I was confused by the fact that no error was reported. @Håkon Hægland points out that the documentation for return
indicates it can be used in sort
block. And indeed it can be used in other circumstances. There's a bug, which I've reported and which has now been fixed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With