SPUG: parameterized push

Michael R. Wolf MichaelRWolf at att.net
Thu Jan 8 21:56:49 CST 2004


I'd like to parameterize the first argument to push.

In the following code, the "if" clause does what I want, but it

 - takes too many lines, 
 - I have to type $_ more than once, 
 - I have to type "push" more than once, 
 - it's got too many punctuation characters
 - it's got too many CR's, and 
 - I'd like to think functionally.

I figured I could do this by using the ternary operator to decide
which array to pass to push. (It could get more "interesting".)

But most importantly, I'm trying to do two transformations on the code
so that it can fit in one line and I can look like a real froody JAPH.

I tried a few ways to parameterize push in the "else" clause, and
eventualy got it to work using a deref of a block that returns a
reference. It works.

Is there an easier (i.e. more readable, and without resorting to
references) way to pass an argument off to push?

Thanks,
Michael

P.S. This decision clause could get more intersting, possibly to
include a multi-way dispatch....

    $arg = something
    # Push in on the appropriate array, or the default array.
    push @{ {key1=>\@array1, key2=>\@array2}->{$arg} || \@array_def }, $_;

    # Simplified to...
    $dispatch_ref = {key1=>\@array1, key2=>\@array2, key3=>\@array3};       
    push @{ $dispatch_ref->{$arg} || \@array_def }, $_;


    @array1, @array2... at arrayN have stuff keyed by $arg
    @array_def contains the rest


================================================================

#! /usr/bin/perl
use warnings;

# Play, play, play -- learn, learn, learn
#   Set $magic_number as a key to the unnamed hash that sets $code_frag,
# defaulting it if $magic_number is not a key.  
my $magic_number = 1;		# Choose 99 for multi-line...
my $code_frag = {3 => "three-line",
		 2 => "two-line",
                 1 => "one-line"}->{$magic_number} || "multi-line";

# $code_frag = "one-line";

if ($code_frag =~ /multi-line/) {
    # This code works fine.
    while (<DATA>) {
        if (1 .. /^\s*$/) {	# Is it 1st line through blank line?
            push @header, $_;
        } else {
            push @body, $_;
        }
    }
} elsif ($code_frag =~ /one-line/) {
    # The commented-out lines don't work.
    # push 1 .. /^\s*$/ ? @header : @body, $_ while (<DATA>);
    # push {1 .. /^\s*$/ ? @header : @body}, $_ while (<DATA>);
    # push eval {1 .. /^\s*$/ ? @header : @body}, $_ while (<DATA>);

    # The first arg to push derefs to be one array or the other. The
    # flip-flop decides if we're in the header (1st line through blank
    # line) or not.

    # Can it get simpler than this????????????
    push @{1 .. /^\s*$/ ? \@header : \@body}, $_ while (<DATA>);
} else {
    die "bad code_frag value";
}


END {			   # Always execute this code, even if we die.

    print "magic_number: $magic_number\n";
    print "code_frag: $code_frag\n";

    print  "\n";
    print "head ", "V"x78, "\n", @header;
    print "body ", "V"x78, "\n", @body;
    print "="x78, "\n";
}

__DATA__
1  head
2  head
3  head
4  head

1  body
2  body
3  body
4  body
5  body
6  body
7  body
LAST LINE OF BODY





More information about the spug-list mailing list