in reply to Passing / evaluating / dieing on one line...

Before this goes any further, I'm going to throw cold water on this "one line" business.

UNLESS YOU ARE WRITING THROW-AWAY CODE, SUCH AS AN OBFUSCATION OR GOLF, DO NOT TRY AND FIT EVERYTHING ON ONE LINE!

Production code (i.e., anything that is used more than once) should be as readable and maintainable as possible. If this means you use 10 lines, then use 10 lines!

(my $label_colnum = &column_exists( \@data, $_[1] || 0 )) == -1 and di +e;
should really look something like
my $second_value = defined $_[1] ? $_[1] : 0; my $label_column = &column_exists(\@data, $second_value); die if $label_column == -1;
Obviously, you'd name $second_value to be something meaningful in your situation. In addition, you're putting on each line one distinct idea.
  1. Set up the second value in the function call.
  2. Do the function call and store the returned value somewhere.
  3. Make sure that the returned value is meaningful.
Human time is the most expensive time in programming. Save human time and you'll be the more effective programmer.

------
We are the carpenters and bricklayers of the Information Age.

Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

Replies are listed 'Best First'.
Re: Re: Passing / evaluating / dieing on one line...
by zengargoyle (Deacon) on Apr 05, 2002 at 15:27 UTC

    Not if it will end up like this:

    (my $label_colnum = &column_exists( \@data, $_[1] || 0 )) == -1 and di +e; (my $key_colnum = &column_exists( \@data, $_[1] || 1 )) == -1 and di +e; (my $cross_colnum = &column_exists( \@data, $_[1] || 2 )) == -1 and di +e; # ...

    It's easier to cut-n-paste, it's obvious to a maintainer how to add another colnum variable.

    If you later want to refactor it's also easier to automate the conversion if the statements are grouped on one line. Simple s/blah (\w) blah (\d) blah die (".*");$/refactorsub(\1,\2,\3);/; or such, no multi-line wierdness ;).

    I tend to think of long identicalish lines as a template or macro or pseudo sub type of thing.

    Which would you prefer?

    do_A; do_B; do_C; do_D; do_A; do_B; do_C; do_E; do_A; do_B; do_C; do_C; or do_A; do_B; do_C; do_D; do_A; do_B; ...

    The yaddayaddayadda (...) is going to be one of my favorite operators in Perl 6 ;)

      Your example is spurious, because it's bad code.
      my %Columns = ( 'label' => 0, 'key' => 1, 'cross' => 2, ); foreach my $col_name (keys %Columns) { $Columns[$col_name} = column_exists( \@data, $_[1] || $Columns{$co +l_name} ); die if $Columns{$col_name} == -1; }
      Now, adding a new column is a matter of changing the %Columns hash. In addition, it's much easier to factor out the %Columns hash to some configuration file this way than doing it your way.

      In addition, this lends itself to even further improvements. For example, consider

      my %Columns = ( 'label' => { default => 0, exists => 0, }, 'key' => { default => 1, exists => 0, }, 'cross' => { default => 2, exists => 0, }, ); foreach my $col_name (keys %Columns) { $Columns[$col_name}{exists} = column_exists( \@data, $_[1] || $Columns{$col_name}{default} ) +; die if $Columns{$col_name}{exists} == -1; }

      THAT is self-documenting code!

      Furthermore, any time I see

      do_A; do_B; do_C; do_D; do_A; do_B; do_C; do_E; do_A; do_B; do_C; do_C;
      I was to do something like:
      for (\&do_D, \&do_E, \&do_C) { do_A; do_B; do_C; $_->(); }
      It's cleaner, more maintainable, and more extensible.

      ------
      We are the carpenters and bricklayers of the Information Age.

      Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

        i can't ++ and -- a node at the same time, and you have a high rep, so i just --'ed this one.

        i like your first example of maintainable code. it could be extended further by variablizing the constant values, like

        sub colNOEXISTS () {-1} # and, then, in the for statement... $Columns{$col_name}{exists} == colNOEXISTS and die "your error here: $!";

        what i don't like is your second example. i think it is difficult for a maintainer to understand that you're evaluating code references using a default variable, as in $_->() for \&do_A;.

        secondly, the do_A; do_B; ... example could have been expressions or blocks, but your example limits do_C, do_D, and do_E to only evaluating code blocks. for instance,

        $i=1; $j=2; $k=3; $l = $i++ * $j++ for 1..$k; $i=1; $j=2; $k=3; $m = $j++ * $k++ for 1..$i; $i=1; $j=2; $k=3; $k=3;
        (which is a somewhat contrived example) cannot easily fit into your method.

        my point: zengargoyle suggested a formatting change to improve maintainability, while you suggested a functionality change. the formatting change is easy to implement and maintain, while your suggestion involves a deeper understanding of the underlying code, and the limitations of the construct which you impose upon it. i believe this has the potential to make code more difficult to maintain and extend, and has a higher potential to be misunderstood.

        ~Particle ;Þ

Re: Re: Passing / evaluating / dieing on one line...
by S_Shrum (Pilgrim) on Apr 05, 2002 at 23:56 UTC

    Wow! What did I do? This node is mutating!

    I can see your point about human time...ultimately, the code is going into a library of subs I'm making and (most of the time) I will never need to look at the code again since I just need it to produce an end result.

    I wrote about 15 small, yet very specialized subs last night and after sleeping on it and coming back, I can see how doing everything step by step may make things easier to follow (and maybe even to code). Granted, in my defense, I'm REALLY BIG on code comments in everything I write so that helps. 8-)

    ======================
    Sean Shrum
    http://www.shrum.net