2

I would've expected all of these to print out 1, 2 and 3. But the last two don't. Why is that?

#!/usr/bin/perl -w
use strict;

sub mysub {
    return (1,2,3);
}

print "--- foreach (mysub()) prints 1, 2 and 3\n";
foreach (mysub()) {
    print $_, "\n";
}

print "--- foreach (mysub) prints 1, 2 and 3\n";
foreach (mysub) {
    print $_, "\n";
}

print "--- foreach (sort(mysub())) prints 1, 2 and 3\n";
foreach (sort(mysub())) {
    print $_, "\n";
}

print "--- foreach (sort mysub()) prints no elements (huh?)\n";
foreach (sort mysub()) {
    print $_, "\n";
}

print "--- foreach (sort mysub) prints a single 'mysub' string (huh?)\n";
foreach (sort mysub) {
    print $_, "\n";
}

It has this output:

--- foreach (mysub()) prints 1, 2 and 3
1
2
3
--- foreach (mysub) prints 1, 2 and 3
1
2
3
--- foreach (sort(mysub())) prints 1, 2 and 3
1
2
3
--- foreach (sort mysub()) prints no elements (huh?)
--- foreach (sort mysub) prints a single 'mysub' string (huh?)
mysub

Why not 1, 2 and 3 in every case? (Perl 5.18.2 on debian jessie)

Peter V. Mørch
  • 13,830
  • 8
  • 69
  • 103
  • 1
    While this looks like a duplicate question, I respectfully suggest that in fact is is not a duplicate of any of the three questions marked above. (I did in fact read every single one of them before posting). As @ikegami points out in his answer, this root cause is really about `sort`. My first two test cases illustrate that `mysub` and `mysub()` behave identically. – Peter V. Mørch Aug 17 '17 at 22:57
  • Re-opened. None of the three questions of which this was supposedly a dup have anything to do with `sort`. – ikegami Aug 17 '17 at 22:57
  • @stevieb, Operator names aren't reserved words in Perl, merely keywords. (e.g. `sub print { }`, `sub and { }`) – ikegami Aug 17 '17 at 23:11

1 Answers1

4

The syntax for sort is:

  • sort SUBNAME LIST
  • sort BLOCK LIST
  • sort LIST

The first is really weird and the source of the problems such as yours.


sort mysub()

sort SUBNAME LIST uses the sub named SUBNAME to sort the list, so sort mysub () asks sort to sort an empty list.


sort mysub

Here, Perl again thinks you're going for sort SUBNAME LIST until it finds no LIST. Having been provided something incorrect, it guesses the string it considered to be a sub name must have been meant to be the list of items to sort.

This situation could be handled better —why would Perl assume you wanted to sort a single constant item?— but the resolution makes more sense when you consider the following:

$ perl -le'my $s = abc; print $s;'
abc

$ perl -le'my ($s) = sort abc; print $s;'
abc

Solutions

  • sort(mysub())[1]
  • sort +mysub()
  • sort +mysub

  1. That parens can't be used with the SUBNAME syntax is rather odd in and of itself. They can be used for the BLOCK syntax (e.g. sort( { $a cmp $b } @a )), and they can be used for in other functions that accept a leading identifier (e.g. print(STDOUT "abc\n");).
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • I just noticed in testing if you do `sort mysub, mysub`, it does the right thing on the first `mysub`, but not the second: `123mysub`. I didn't realize until I tested that, that it was a `sort` thing and not a perl thing. – stevieb Aug 17 '17 at 22:42