Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return from sort block gives "Use of uninitialized value in sort" warning, but only with explicit return

Tags:

perl

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 /;

Question 0

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.

Question 1

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.

like image 650
amphetamachine Avatar asked Aug 14 '20 18:08

amphetamachine


People also ask

Why there are so many sort blocks in SSIs?

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.

Is the column with the sortkeyposition value of 1 valid?

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 “.

Why sorting in SSIs package takes more time than in source?

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:

Why is there no sort operator in the first plan?

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.


1 Answers

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.

like image 58
ikegami Avatar answered Oct 17 '22 03:10

ikegami