Unobvious Pathological Code Snippets
QM
created: 2006-03-28 10:33:02
While considering this bit of code again:
perl -pe'}{$_=$.' filename
and the implications of the implied continue, I wondered outloud about unobvious pathologies in general. Consider, for your amusement, what this does:
for (qw(Whom the bell tolls)) {}
continue { print "$_\n"; next }
[We could argue that this example should produce a warning, but this post is really about enjoying the quirks, and not about fixing them.]

What pathologies twist the corners of your mouth?

-QM
--
Quantum Mechanics: The dreams stuff is made of

Re: Unobvious Pathological Code Snippets
created: 2006-03-28 12:12:11
A recent favorite, noted by [Dominus], is that your example could be rewritten as:

for qw(Whom the bell tolls) {}            # huh? for qw() ?
continue { print "$_\n"; next }

Re^2: Unobvious Pathological Code Snippets
created: 2006-03-28 12:16:57
But only on fairly modern Perl versions. I think that qw() syntax didn't work in 5.5 and older.

-- Randal L. Schwartz, Perl hacker
Be sure to read my standard disclaimer if this is a reply.

Re^3: Unobvious Pathological Code Snippets
created: 2006-03-28 15:04:10
It's not like this is intended behavior :)

My other favorite is even sicker and more useful. Credit this time to audreyt++ who checked this into pugs with the commit message

do not mention $@% in the Makefile for portability

We had a one-liner that was breaking differently on different platforms. Insane desugaring to the rescue!

-       \$(PERL) -MFile::Spec -e "my (undef, \$\$dir, \$\$file) = File::Spec->splitpath(shift); chdir(\$\$dir); system(q+$hsc2hs $hsc2hs_flags + . \$\$file);" \$<
+       \$(PERL) -MFile::Spec -e "sub p () { File::Spec->splitpath(ARGV->[0]) }; chdir((p)[1]); system(q($hsc2hs), qw($hsc2hs_flags), (p)[2]);" \$<
(The thing to note here is ARGV->[n].)
Re^2: Unobvious Pathological Code Snippets
created: 2006-03-31 19:42:58
Am I missing something? With perl 5.8.8 in linux I get an error:
poletti@PolettiX:~/sviluppo/perl$ perl pathological.pl
Missing $ on loop variable at pathological.pl line 1.
poletti@PolettiX:~/sviluppo/perl$ 
poletti@PolettiX:~/sviluppo/perl$ 
poletti@PolettiX:~/sviluppo/perl$ cat pathological.pl
for qw(Whom the bell tolls) {}            # huh? for qw() ?
continue { print "$_\n"; next }
while the OP's example...

Flavio
perl -ple'$_=reverse' << Don't fool yourself.

Re^3: Unobvious Pathological Code Snippets
created: 2006-04-01 02:49:31
Oops, ()-less qw requires a loop variable. Fixed.
Re: Unobvious Pathological Code Snippets
created: 2006-03-28 13:11:34

This, (attributable to [Juerd]) is kinda cute, and a little surprising:

my @a = '01' .. '30';
print "@$_" for sub{
    my $n=shift; 
    map{ [ splice @_, 0, $n ] } 0 .. @_ / $n 
}->( 5, @a );

01 02 03 04 05
06 07 08 09 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
26 27 28 29 30

print @a;
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
Re^2: Unobvious Pathological Code Snippets
QM
created: 2006-03-28 13:52:33
<Tim "The Toolman" Taylor>

Hrruuhhhh???

</Tim "The Toolman" Taylor>

While that's devilish and all that, how is it pathological? Heck, it doesn't even DWIM unless $n divides @_.

The interesting bit, to me, is passing arguments to the anonymous sub.

I guess I should have stated more explicitly that I'm looking for things that can't be grokked without deep diving into the docs or the source code. For instance, the continue/next behavior is documented, rather humorously, as "entertaining", without being so explicit as to spoil the fun.

-QM
--
Quantum Mechanics: The dreams stuff is made of

Re^3: Unobvious Pathological Code Snippets
created: 2006-03-28 14:44:14

The thing to note is that despite having "destructively" spliced the array into chunks, the array remains unchanged after the process.


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
Re^4: Unobvious Pathological Code Snippets
QM
created: 2006-03-28 15:17:11
Oh, OK. I wasn't expecting this, but it's within the parameters, Jim ;)

Is it then a copy instead of the original?

So what are the critical characteristics? Is it the anonymous sub? The map? Or the whole gestalt? (And is "whole gestalt" pleonastic?)

-QM
--
Quantum Mechanics: The dreams stuff is made of

Re^5: Unobvious Pathological Code Snippets
created: 2006-03-28 16:30:03

See Juerd's original thread: node 228501 for some explanation/discussion.

How it works, as I understand, and anyone knows better, please correct me.

When you pass an array to a sub, each of the elements of @_ is alias to the elements of the original array. As the destructive manipulations are applied to @_ rather than the original array, the original array and it's contents remain untouched by the process.


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
Re^6: Unobvious Pathological Code Snippets
xdg
created: 2006-03-28 18:16:58

It's really no different than a shift.

If I understand perlsub, the subtlety here is that @_ itself is not an alias to the original array/list of arguments -- rather, @_ is a local array with each element an alias to the corresponding element in the argument list -- which is why you can shift, pop or (as in this case) splice @_ at will.

However, assigning to @_ or even using splice to overwrite part of an array, destroys that aliasing for whatever is overwritten. Thus:

use strict;
use warnings;

sub splice_insert {
    splice( @_, 2, 2, ('a' .. 'c') );
    print "@_ # after splice\n";
    $_ = '.' for @_;
    print "@_ # after for loop\n";
}

my @a = ( 0 .. 6 );

print "@a   # before subroutine\n";

splice_insert(@a);

print "@a   # after subroutine\n";

Prints:

0 1 2 3 4 5 6   # before subroutine
0 1 a b c 4 5 6 # after splice
. . . . . . . . # after for loop
. . 2 3 . . .   # after subroutine

-xdg

Code written by xdg and posted on PerlMonks is [http://creativecommons.org/licenses/publicdomain|public domain]. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re: Unobvious Pathological Code Snippets
hv
created: 2006-03-28 21:07:04

Here's a couple:

  zen% perl -we '$|--; print $|; $|--; print $|; print --$|, --$|, $|--, $|--, $/'
  100001
  zen% 

Hugo

perlmonks.org content © perlmonks.org and BrowserUk, frodo72, gaal, hv, merlyn, QM, xdg

prlmnks.org © 2006 edmund von der burg (eccles & toad)

v 0.03