Does Perl v5.18's sort understand lexical subroutines?
Asked Answered
M

1

9

This is fixed in Perl v5.22.


Does Perl v5.18's lexical subroutines with sort? I finally had a use for them today where I had a complicated sorting routine that depends on the current position in the data structure to look at deeper parts.

Here's a small program:

use v5.18;
use feature qw(lexical_subs);
no warnings qw(experimental::lexical_subs);

my sub by_numbers { $a <=> $b }

my @sorted = sort by_numbers qw( 4 8 2 3 0 5 7 6 1 9 );

say "sorted: @sorted";

Apparently sort knows nothing about this because it is still looking in %main:: for the named subroutine:

% perl5.18.2 test.pl
Undefined sort subroutine "main::by_numbers" called at test.pl line 7.

% perl5.20.1 test.pl
Undefined sort subroutine "main::by_numbers" called at test.pl line 7.

I'm a bit disappointed because this is the first use case that rjbs uses in lexical subroutines in perl 5.


This part doesn't matter because I looked at the current version of the test instead of the v5.18 version.

I look it t/op/lexsub.t in the perl source, I find three tests that involve sort. They fail when run in isolation, and differ in a major way: there's a defined subroutine of the same name in the symbol table (as rjbs notes, these tests come from the current source and were not present in the affected stable releases.):

use v5.18;
use feature qw(lexical_subs);
no warnings qw(experimental::lexical_subs);

use Test::More;

sub _cmp { $a cmp $b }
sub bar::_cmp { $b cmp $a }
{
  package bar;
  our sub _cmp;
  package main;
  is join(" ", sort _cmp split //, 'oursub'), 'u u s r o b', 'sort our_sub'
}


{
  state sub _cmp { $b cmp $a }
  is join(" ", sort _cmp split //, 'lexsub'), 'x u s l e b',
    'sort state_sub LIST'
}

{
  my sub _cmp { $b cmp $a }
  is join(" ", sort _cmp split //, 'lexsub'), 'x u s l e b',
    'sort my_sub LIST'
}

sort completely ignores the lexical subroutines in all cases (for perls v5.18 and v5.20):

not ok 1 - sort our_sub
#   Failed test 'sort our_sub'
#   at test.pl line 29.
#          got: 'b o r s u u'
#     expected: 'u u s r o b'
not ok 2 - sort state_sub LIST
#   Failed test 'sort state_sub LIST'
#   at test.pl line 35.
#          got: 'b e l s u x'
#     expected: 'x u s l e b'
not ok 3 - sort my_sub LIST
#   Failed test 'sort my_sub LIST'
#   at test.pl line 41.
#          got: 'b e l s u x'
#     expected: 'x u s l e b'
# Tests were run but no plan was declared and done_testing() was not seen.

Besides this testing being problematic since it fails to isolate the environment, it's also tough to tell what the tester is doing and how much of the previous, far away setup each test demands. The tests themselves are lightly documented, if at all.


back to stuff mattering

Am I missing something here? It seems this never worked. The trick then, is what in the test file allows it to pass?

Please don't suggest workarounds. That's not why I'm asking.

Mayotte answered 13/1, 2015 at 2:10 Comment(0)
T
13

I'd like to say that this was working in v5.17.x and then got broken, but it looks like everyone missed it, and I missed even verifying that it worked. So… it doesn't. Or, much more happily, it didn't. This was fixed in:

commit 2872f91877d2b05fa39d7cd030f43cd2ebc6b046
Author: Father Chrysostomos <[email protected]>
Date:   Tue Sep 16 13:10:38 2014 -0700

    Make sort bareword respect lexical subs

—something I completely missed when implementing them.

…and since v5.21.4, this has worked as expected and promised.

Typhoid answered 13/1, 2015 at 2:32 Comment(6)
Ah hell. I knew I should have tried the latest bleed but I was lazy. How does it pass the tests in earlier perls though?Mayotte
Sorry, I'm not sure which tests you mean. lexsub.t didn't have sort tests in v5.20.0, for example: github.com/Perl/perl5/blob/v5.20.0/t/op/lexsub.tTyphoid
Ah, I was looking at the current source. Okay, that explains that. Will these fixes be backported to the current officially supported versions of Perl?Mayotte
I don't think so. In theory, we backport bugfixes in experimental features when they "can't" break code not using those features, but I'm guessing this would be borderline. I'll ask Steve Hay, the v5.20 manager, his opinion.Typhoid
If you decide not to fix it (and in 5.18 too), how about a doc patch for the next release noting it's failure to work?Mayotte
This "known bug" report was added in 78dc438 and is in the docs for v5.20.2. I've just cherry picked it to maint-5.18, and it will be in the next 5.18 release, if any.Typhoid

© 2022 - 2024 — McMap. All rights reserved.