Applying ideas from new languages in your old standbys

Aristotle on 2009-12-04T10:35:19

I just wrote the following Perl 5 code. Consider the bolded bits, and think about what the code would have looked like if I had tried to write it in any equally DRY way using map.

sub new {
    my $class = shift;
    my $self = bless { @_ }, $class;
    my $builder = $self->builder;
    my $content = $self->content;

    my ( @gather, @take );

    for my $r ( XML::Builder::Util::is_raw_array( $content ) ? @$content : $content ) {
        @take = $r;


        if ( not Scalar::Util::blessed $r ) {
            @take = $builder->render( @_ ) if XML::Builder::Util::is_raw_array $r;
            next;
        }

        if ( not $r->isa( $builder->fragment_class ) ) {
            @take = $builder->stringify( $r );
            next;
        }

        next if $builder == $r->builder;

        Carp::croak( 'Cannot merge XML::Builder fragments built with different namespace maps' )
            if $r->depends_ns_scope;

        @take = $r->flatten;

        my ( $self_enc, $r_enc ) = map { lc $_->encoding } $builder, $r->builder;
        next
            if $self_enc eq $r_enc
            # be more permissive: ASCII is one-way compatible with UTF-8 and Latin-1
            or 'us-ascii' eq $r_enc and grep { $_ eq $self_enc } 'utf-8', 'iso-8859-1';

        Carp::croak(
            'Cannot merge XML::Builder fragments with incompatible encodings'
            . " (have $self_enc, fragment has $r_enc)"
        );
    }
    continue {
        push @gather, @take;
    }


    $self->{'content'} = \@gather;

    return $self;
}

I don’t know whether this way of writing the code would have occurred to me if I hadn’t seen the construct in Perl 6. I suspect not.