My Perl hero of the week: Eric Strom (ASG)

http://search.cpan.org/~asg/

Hash-Abbrev-0.01  Text::Abbrev with aliases
List-Gen-0.96         provides functions for generating lists
Lvalue-0.21            add lvalue getters and setters to existing objects
Perl6-Feeds-0.20       implements perl6 feed operators in perl5 via source filtering
Test-Magic-0.21    terse tests with useful error feedback
Whatever-0.21       a perl6ish whatever-star for perl5
XUL-Gui-0.63         render cross platform gui applications with firefox from perl

He seems to be seriously into functional programming, Haskell and perl6 alike, which seems to be totally weird.

E.g. look what he is doing with us:

use List::Gen;

print "@$_\n" for every 5 => 1 .. 15;
# 1 2 3 4 5
# 6 7 8 9 10
# 11 12 13 14 15

print mapn {"$_[0]: $_[1]\n"} 2 => %myhash;

my $ints    = <0..>;
my $squares = gen {$_**2} $ints;

say "@$squares[2 .. 6]"; # 4 9 16 25 36

$ints->zip('.', -$squares)->say(6); # 0-0 1-1 2-4 3-9 4-16 5-25

list(1, 2, 3)->gen('**2')->say; # 1 4 9

my $fib = ([0, 1] + iterate {fib($_, $_ + 1)->sum})->rec('fib');
my $fac = iterate {$_ < 2 or $_ * self($_ - 1)}->rec;

say "@$fib[0 .. 15]";  #  0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610
say "@$fac[0 .. 10]";  #  1 1 2 6 24 120 720 5040 40320 362880 3628800

say <0, 1, * + * ...>->take(10)->str;   # 0 1 1 2 3 5 8 13 21 34
say <[..*] 1, 1..>->str(8);             # 1 1 2 6 24 120 720 5040

<**2 for 1..10 if even>->say;           # 4 16 36 64 100

<1..>->map('**2')->grep(qr/1/)->say(5); # 1 16 81 100 121

Gather/Take is also somewhere, though it's no real take as shown at YAPC::EU 2011 by this german guy from Frankfurt.pm. (...)

But look at the other modules:

use Whatever;
my $greet = 'hello, ' . &* . '!';
say $greet->('world'); # prints 'hello, world!'

my $result = $someobj->map(sub{$_ * 2});
# simplified as
my $result = $someobj->map(&* * 2);

&* is interpolated into the arg if called as function. Any SV with &* is treated as CVREF with special &* handling. No need to write lots of anonymous subs anymore.

Or look at Lvalue which creates setters and getters for any Class fields.

sub overload {
    my ($object, $proxy) = @_;
    my $pkg = ref $object;
    my $overloader = sub {
        my $op = shift;
        sub {
            if (my $sub = overload::Method($pkg, $op)) {
                @_ = ($object, @_[1, 2]);
                goto &$sub;
            }
            Carp::croak "no overload method '$op' in $pkg";
        }
    };
    no strict 'refs';
    my $fallback = ${$pkg.'::()'};

    my $overload = join ', ' =>
        defined $fallback ? 'fallback => $fallback' : (),
        map "'$_' => \$overloader->('$_')" =>
            grep s/^\((?=..)// => keys %{$pkg.'::'};

    eval qq {package $proxy;
        our \@ISA = 'Lvalue::Loader';
        use overload $overload;
    } or Carp::carp "Lvalue: overloading not preserved for $pkg, "
                  . "bug reports or patches welcome.\n  $@";
}

This works but is way over my head. Hope to understand it some day.

The crown jewel is XUL::Gui

With super simple syntax he creates a full XUL binding, which enables modern cross-platform GUIs, remote or locally. There's a event-loop, it totally looks like Tcl/Tk, just with a better language (HTML and Perl) and easier to learn. Everybody knows HTML, but who can remember Win32::GUI, Tcl/Tk and all the other GUI frameworks. For non-mozilla browsers there is Web::GUI as the limited version of it. But you can always ship or download xulrunner.

use XUL::Gui;
display Label 'hello, world!';

use XUL::Gui;
display Window title => "XUL::Gui's long hello",
    GroupBox(
        Caption('XUL'),
        Button(
            label     => 'click me',
            oncommand => sub {$_->label = 'ouch'}
        ),
        Button(
            id        => 'btn',
            label     =>'automatic id registration',
            oncommand => sub {
                ID(btn)->label = 'means no more variable clutter';
                ID(txt)->value = 'and makes cross tag updates easy';
        }),
        Button(
            type  => 'menu',
            label => 'menu button',
            MenuPopup map
                {MenuItem label => $_} qw/first second third/
        ),
        TextBox( id => 'txt', width => 300 ),
        ProgressMeter( mode => 'undetermined' ),
    ),
    GroupBox(
        Caption('HTML too'),
        TABLE( width => '100%',
            TR map {TD $_}
                'one', I('two'), B('three'), U('four'), SUP('five')
        ),
        BR, HR,
        P('all the HTML tags are in CAPS'),
    );

1 Comment

Seconded. XUL::Gui is wonderful. Though the run-time detection of your Gecko engine of choice has caused me a few problems.

Leave a comment

About Reini Urban

user-pic Working at cPanel on B::C (the perl-compiler), p2, types, parrot, B::Generate, cygwin perl and more guts (LLVM, jit, optimizations).