Just Another Godel, Escher, Bach hacker
FoxtrotUniform
created: 2004-06-25 15:31:17

What this obfu lacks in artistic merit (that's supposed to be a Möbius strip), I think it makes up in technique and name. I got the idea from a Haskell assignment (egads! Posting homework to the monastery?), and I think the main concept is mildly clever. I'd love to talk about it, but I don't want to spoil the surprise!

#! /usr/bin/perl -w

use strict;

 sub godel{my ($f,$a,$l)=@_;return $a  unless @$l;my$x=shift @$l;&$f(
$x,&godel($f,$a,$l));}my @M=split '',  "Just another ";my @I =split '', 
"Perl hacker,"; my                                  @U =reverse @M; sub
escher{my ($l,$m)                                    =@_;sub{$l= pop @U
if @U;$l.&$m();} }                                  unshift@U, split ''
,"pool egnarts";my$bach=&godel(\&escher,&godel(\&escher,sub{return"\n"}
 ,\@I),\@M);print &$bach(); ### Inspired by Douglas Hofstadter's _GEB_

Tested on Perl 5.6.1, Linux 2.4.18.

--
F o x t r o t U n i f o r m
Found a typo in this node? /msg me
% man 3 strfry

Re: Just Another Godel, Escher, Bach hacker
created: 2004-06-25 16:10:51

Nice. Reading this was like comfort food.

There's a spoiler in the readmore.

  1. Fill @M with "Just another "
  2. Fill more with "strange loop"
  3. Nested godels on the stack while the global @U has data so the "Perl hacker," portion is just overwritten during $l = of escher(). Here \@I is just an iterator (though it contains some tantalizingly familiar data) so that @U can be popped properly.
    P( e( r( l( ( h( a( c( k( r( ,( "\n" ) ) ) ) ) ) ) ) ) ) )
  4. Pretend to do something with @M though really this is just another loop to go extract more stuff from the global @U.
    J( u( s( t( ( a( n( o( t( h( e( r( "strange loop" ) ) ) ) ) ) ) ) ) ) ) )
  5. print
#! /usr/bin/perl -w
use strict;
use vars qw( @U );

my @M = split '',  "Just another ";
my @I =split '', "Perl hacker,";
@U = reverse @M;
unshift( @U,
         split '',
         "pool egnarts" );
print godel( godel( sub{ "\n" },
                    \ @I ),
             \ @M )->();

sub godel
{
    my ($a, $l) = @_;
    return $a unless @$l;
    my $x = shift @$l;

    return escher( $x,
                   godel( $a, $l ) ) ;
}

sub escher
{
    my ($l, $m) = @_;

    return
        sub
        {
            $l = pop @U if @U;
            return $l . $m->();
        };
}
Re^2: Just Another Godel, Escher, Bach hacker
created: 2004-06-25 19:01:02

Nice summary! (readmore is spoily)

You missed a subtlety about godel, though. What it's actually doing is nesting anonymous calls to the sub returned by escher, which do the extraction from @U. The whole thing returns a sub, which calls more subs nested in the closure, and so on, and so on; that's the part I think is cool.

godel is equivalent to foldr in Language::Functional (or Haskell, for that matter); escher is the combining function, and sub {"\n"} is the start value.

--
F o x t r o t U n i f o r m
Found a typo in this node? /msg me
% man 3 strfry

Re^3: Just Another Godel, Escher, Bach hacker
created: 2004-06-26 00:53:13

Oh well yeah, each recursive godel() generates another function via escher() which has a bit more of the overall string. I sort of implied that in the stack.

So if perl were Haskell, what else would you have here?

perlmonks.org content © perlmonks.org and diotalevi, FoxtrotUniform

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

v 0.03