The following script tests several variants of a function that opens and returns a lexical filehandle. The versions differ only in the way arguments are passed to open, and they are tested under two conditions: the file to be written to does not already exist, or it does. I show the results of running the script immediately after the code:

use strict; use warnings FATAL => 'all'; my @open = ( q(open( my $fh, @_ )), q(open( my $fh, @_[ 0..$#_ ] )), q(open( my $fh, shift, @_ )), ); my $filename = 'hello_world'; my $test_string = "Hello, world!\n"; for my $prepare ( \&remove, \&truncate ) { for my $o ( @open ) { my $sub = eval "sub { $o or die \$!; return \$fh }" or die 'eval failed'; $prepare->( $filename ); # remove or truncate eval { my $fh = $sub->( '>', $filename ); print $fh $test_string; close $fh; $test_string eq `cat $filename` or die "incorrect contents\n"; }; printf "%-33s: %s", $o, $@ ? $@ : "OK\n"; } print "\n"; } sub remove { unlink shift; } sub truncate { open my $fh, '>', shift or die $!; return; } __END__ open( my $fh, @_ ) : No such file or directory at (eval +1) line 1. open( my $fh, @_[ 0..$#_ ] ) : No such file or directory at (eval +2) line 1. open( my $fh, shift, @_ ) : OK open( my $fh, @_ ) : No such file or directory at (eval +5) line 1. open( my $fh, @_[ 0..$#_ ] ) : Filehandle $fh opened only for inpu +t at pita.pl line 25. open( my $fh, shift, @_ ) : OK

That the first version fails did not surprise me too much, since I know some functions distinguish between arrays and lists in their input, but the failure of the second version does surprise me, especially because the particular nature of the failure depends on whether the file already exists or not.

Incidentally, the second error for the second version ("Filehandle $fh opened only for input...") is actually only a warning; I have rendered it fatal for the purpose of this analysis.

I found the working version by trial and error, but this is annoying. Programming something this simple should not be an experimental science. Besides, without testing all sorts of combinations of inputs, I can't tell whether it will work in general.

Is there any principle that I could invoke to short-circuit this process? Or is it "just one of those things" that one has to live with?

the lowliest monk


In reply to open annoyance by tlm

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.