Odd sort() problem

1

187

I friend of mine recently accessed me for a little one liner to nicely
display all the paths in the $PATH vartiable on his NT 5.1 (aka XP Pro)
machine: (sorry for word wrap)

C:\> perl -e "print qq{\n}, join(qq{\n}, sort { lc{$a} cmp lc($b) }
split(/;/, $ENV {'PATH'})), qq{\n};"

C:\Program Files\Borland\JBuilder6\jdk1.3.1\bin
C:\Program Files\Executive Software\Diskeeper\
C:\Program Files\ATI Technologies\ATI Control Panel
C:\usr\local\wbin
C:\Inetpub\wwwroot\perl\bin\
C:\PROGRA~1\Borland\CBUILD~1\Projects\Bpl
C:\PROGRA~1\Borland\CBUILD~1\Bin
C:\Inetpub\wwwroot\perl\bin
C:\WINDOWS\system32
C:\WINDOWS
C:\WINDOWS\System32\Wbem


I get the same sort of oddness on my Linux machine as well:

$ perl -e 'print qq{\n}, join(qq{\n}, sort { lc{$a} cmp lc($b) }
split(/:/, $ENV{"PATH"})), qq{\n};'

/home/oracle/OraHome1/bin
/usr/bin
/usr/X11R6/bin
/misc/java/sdk/j2sdk1.4.1_02/bin
/home/bigal187/bin
/usr/sbin
/sbin
/usr/local/bin
/usr/local/sbin
/usr/local/BerkeleyDB.4.2/bin/
/usr/lib/qt/bin
/bin

Both Perl's are 5.6.1, though my Linux also has 5.8.2 which does
similar, though different order:

$ perl5.8.2 -e 'print qq{\n}, join(qq{\n}, sort { lc{$a} cmp lc($b) }
split(/:/, $ENV{"PATH"})), qq{\n};'

/home/oracle/OraHome1/bin
/home/bigal187/bin
/misc/java/sdk/j2sdk1.4.1_02/bin
/usr/X11R6/bin
/usr/bin
/usr/sbin
/bin
/sbin
/usr/local/bin
/usr/local/sbin
/usr/local/BerkeleyDB.4.2/bin/
/usr/lib/qt/bin

What is going on here? Why is sort doing this? I've used sort(), map(),
and grep() in cascaded form like this before without this problem;
split() returns an array, which get sucked into sort(), who spits it
back out to join(), does it not?
 
A

A. Sinan Unur

I friend of mine recently accessed me for a little one liner to nicely
display all the paths in the $PATH vartiable on his NT 5.1 (aka XP Pro)
machine: (sorry for word wrap)

C:\> perl -e "print qq{\n}, join(qq{\n}, sort { lc{$a} cmp lc($b) }
split(/;/, $ENV {'PATH'})), qq{\n};"

I like one liners but I avoid them precisely for this type of problem:
lc{$a} should be lc($a) or just lc $a.

So, the problem is not sort :)
 
1

187

A. Sinan Unur said:
I like one liners but I avoid them precisely for this type of problem:
lc{$a} should be lc($a) or just lc $a.

Oh, the humanity! Actually I tend to stay away from them too, but my
friend wanted a simple one liner that could stick into a dos BATch file,
and not using any external scripts, which I prefer to use instead.

But what I really don't understand is why it doesn't result in a compile
error? lc{$a}, one would think, is not a valid statement.

I admit should I have used -w in there:

Odd number of elements in anonymous hash at -e line 1.
Odd number of elements in anonymous hash at -e line 1.
Odd number of elements in anonymous hash at -e line 1.
[......]

Then proceeds to print in random order. (That is, before I fixed it.)
So, the problem is not sort :)

I didn't think it was :)
 
P

Paul Lalli

187 said:
But what I really don't understand is why it doesn't result in a compile
error? lc{$a}, one would think, is not a valid statement.

The warning below answers this question.
I admit should I have used -w in there:

Odd number of elements in anonymous hash at -e line 1.
Odd number of elements in anonymous hash at -e line 1.
Odd number of elements in anonymous hash at -e line 1.
[......]

You're passing to the lc() function an anonymous hash. That anonymous
hash is poorly constructed, containing an odd number of elements. So it
is not invalid syntax, it's just not at all what you meant.

Paul Lalli
 
1

187

Paul said:
The warning below answers this question.

But shouldn't it be complaining either that lc{ } is an undefined hash
or lc being a bareword?

Even if I add 'use strict;' before the print statement (or -Mstrict).
I admit should I have used -w in there:

Odd number of elements in anonymous hash at -e line 1.
Odd number of elements in anonymous hash at -e line 1.
Odd number of elements in anonymous hash at -e line 1.
[......]

You're passing to the lc() function an anonymous hash. That anonymous
hash is poorly constructed, containing an odd number of elements. So
it is not invalid syntax, it's just not at all what you meant.

But should it not interpret lc{} as a bareword hash, and therefore issue
an error about bareword? I'm askign in case this is actually a bug.
 
P

Paul Lalli

187 said:
But shouldn't it be complaining either that lc{ } is an undefined hash
or lc being a bareword?

Of course not. lc is a built in function. it's taking whatever comes
after "lc" as the parameter you're passing to lc. In this case, what
follows is an anonymous hash, signified by the { }
Even if I add 'use strict;' before the print statement (or -Mstrict).


But should it not interpret lc{} as a bareword hash, and therefore issue
an error about bareword? I'm askign in case this is actually a bug.

No. It's not a bug. It's a problem with your belief that { } are used
only to get at an elment of an existing hash. What you did was
equivalent to this:
$ref = {$a}; #assign a poorly-constructed hashref to $ref;
lc $ref; #pass that hash reference as a parameter to the lc function.

Paul Lalli
 
J

John W. Krahn

187 said:
I friend of mine recently accessed me for a little one liner to nicely
display all the paths in the $PATH vartiable on his NT 5.1 (aka XP Pro)
machine: (sorry for word wrap)

C:\> perl -e "print qq{\n}, join(qq{\n}, sort { lc{$a} cmp lc($b) }
split(/;/, $ENV {'PATH'})), qq{\n};"

[snip]

I get the same sort of oddness on my Linux machine as well:

$ perl -e 'print qq{\n}, join(qq{\n}, sort { lc{$a} cmp lc($b) }
split(/:/, $ENV{"PATH"})), qq{\n};'

[snip]

Both Perl's are 5.6.1, though my Linux also has 5.8.2 which does
similar, though different order:

$ perl5.8.2 -e 'print qq{\n}, join(qq{\n}, sort { lc{$a} cmp lc($b) }
split(/:/, $ENV{"PATH"})), qq{\n};'

[snip]

What is going on here? Why is sort doing this? I've used sort(), map(),
and grep() in cascaded form like this before without this problem;
split() returns an array, which get sucked into sort(), who spits it
back out to join(), does it not?

As others have pointed out the problem is with the anonymous hash in "lc{$a}"
however if you want to make this more portable and remove all those quotes and
braces and parentheses:

perl -e 'use Env q/@PATH/; print $/, map $_ . $/, sort { lc $a cmp lc $b } @PATH'


John
 
S

Sid Norman

Paul Lalli said:
Of course not. lc is a built in function. it's taking whatever comes
after "lc" as the parameter you're passing to lc. In this case, what
follows is an anonymous hash, signified by the { }

Actually lc{ } should be seen as a named block, according to PerlDoc.
This is indeed a broken occurance, and should be reported.
No. It's not a bug.

Yes it is - see above.
It's a problem with your belief that { } are used
only to get at an elment of an existing hash. What you did was
equivalent to this:
$ref = {$a}; #assign a poorly-constructed hashref to $ref;
lc $ref; #pass that hash reference as a parameter to the lc function.

No, it's actually more like

lc{
a;
}

It's a named block.
 
1

187

John said:
187 said:
I friend of mine recently accessed me for a little one liner to
nicely display all the paths in the $PATH vartiable on his NT 5.1
(aka XP Pro) machine: (sorry for word wrap)

C:\> perl -e "print qq{\n}, join(qq{\n}, sort { lc{$a} cmp lc($b)
} split(/;/, $ENV {'PATH'})), qq{\n};"

[snip]

I get the same sort of oddness on my Linux machine as well:

$ perl -e 'print qq{\n}, join(qq{\n}, sort { lc{$a} cmp lc($b) }
split(/:/, $ENV{"PATH"})), qq{\n};'

[snip]

Both Perl's are 5.6.1, though my Linux also has 5.8.2 which does
similar, though different order:

$ perl5.8.2 -e 'print qq{\n}, join(qq{\n}, sort { lc{$a} cmp
lc($b) } split(/:/, $ENV{"PATH"})), qq{\n};'

[snip]

What is going on here? Why is sort doing this? I've used sort(),
map(), and grep() in cascaded form like this before without this
problem; split() returns an array, which get sucked into sort(), who
spits it back out to join(), does it not?

As others have pointed out the problem is with the anonymous hash in
"lc{$a}" however if you want to make this more portable and remove
all those quotes and braces and parentheses:

perl -e 'use Env q/@PATH/; print $/, map $_ . $/, sort { lc $a cmp lc
$b } @PATH'

Thanks.
 
P

Paul Lalli

Sid said:
Actually lc{ } should be seen as a named block, according to PerlDoc.
This is indeed a broken occurance, and should be reported.

Can you be more specific? What perldoc section is this in? I'd be most
interested in seeing it.

Paul Lalli
 
A

Anno Siegel

Sid Norman said:
Actually lc{ } should be seen as a named block, according to PerlDoc.
This is indeed a broken occurance, and should be reported.

You don't know what you're talking about.

Anno
 
T

Tad McClellan

I am unaware of this "named block" feature in Perl.

Where exactly could I read up on it?
 
P

Paul Lalli

Tad McClellan said:
PerlDoc.

I am unaware of this "named block" feature in Perl.

Where exactly could I read up on it?

Please keep track of your attributions. Putting words in my mouth isn't
nice.

Paul Lalli
 
D

Douglas Wilson

Tad McClellan said:
I am unaware of this "named block" feature in Perl.

Where exactly could I read up on it?

Perhaps he meant "labeled" block, which is indirectly mentioned
in perlsyn, but which the block being referred to most definitely
is not, since there is no ":" following the "lc".
 
T

Tony Skelding

John W. Krahn said:
187 said:
I friend of mine recently accessed me for a little one liner to nicely
display all the paths in the $PATH vartiable on his NT 5.1 (aka XP Pro)
machine: (sorry for word wrap)

C:\> perl -e "print qq{\n}, join(qq{\n}, sort { lc{$a} cmp lc($b) }
split(/;/, $ENV {'PATH'})), qq{\n};"

[snip]

I get the same sort of oddness on my Linux machine as well:

$ perl -e 'print qq{\n}, join(qq{\n}, sort { lc{$a} cmp lc($b) }
split(/:/, $ENV{"PATH"})), qq{\n};'

[snip]

Both Perl's are 5.6.1, though my Linux also has 5.8.2 which does
similar, though different order:

$ perl5.8.2 -e 'print qq{\n}, join(qq{\n}, sort { lc{$a} cmp lc($b) }
split(/:/, $ENV{"PATH"})), qq{\n};'

[snip]

What is going on here? Why is sort doing this? I've used sort(), map(),
and grep() in cascaded form like this before without this problem;
split() returns an array, which get sucked into sort(), who spits it
back out to join(), does it not?

As others have pointed out the problem is with the anonymous hash in "lc{$a}"
however if you want to make this more portable and remove all those quotes and
braces and parentheses:

perl -e 'use Env q/@PATH/; print $/, map $_ . $/, sort { lc $a cmp lc $b } @PATH'


John

Or even

perl -le 'print for sort { lc $a cmp lc $b } split ":", $ENV{PATH}'
 
1

187

Tony said:
John W. Krahn said:
187 said:
I friend of mine recently accessed me for a little one liner to
nicely display all the paths in the $PATH vartiable on his NT 5.1
(aka XP Pro) machine: (sorry for word wrap)

C:\> perl -e "print qq{\n}, join(qq{\n}, sort { lc{$a} cmp
lc($b) } split(/;/, $ENV {'PATH'})), qq{\n};"

[snip]

I get the same sort of oddness on my Linux machine as well:

$ perl -e 'print qq{\n}, join(qq{\n}, sort { lc{$a} cmp lc($b) }
split(/:/, $ENV{"PATH"})), qq{\n};'

[snip]

Both Perl's are 5.6.1, though my Linux also has 5.8.2 which does
similar, though different order:

$ perl5.8.2 -e 'print qq{\n}, join(qq{\n}, sort { lc{$a} cmp
lc($b) } split(/:/, $ENV{"PATH"})), qq{\n};'

[snip]

What is going on here? Why is sort doing this? I've used sort(),
map(), and grep() in cascaded form like this before without this
problem; split() returns an array, which get sucked into sort(),
who spits it back out to join(), does it not?

As others have pointed out the problem is with the anonymous hash in
"lc{$a}" however if you want to make this more portable and remove
all those quotes and braces and parentheses:

perl -e 'use Env q/@PATH/; print $/, map $_ . $/, sort { lc $a cmp
lc $b } @PATH'


John

Or even

perl -le 'print for sort { lc $a cmp lc $b } split ":", $ENV{PATH}'

Though its not as portable as the quoted one above yours, as different
OS's use different seperators in the PATH variable; example: unix uses a
colon, where as win32 uses a semicolon, hence why the "use ENV q/@PATH/
" is so handy.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top