in reply to Re: Re: Re: Problem creating a function
in thread Problem creating a function

What's the big deal.

Here is an example. You are calling cleaner in some sub that is not always called in the CGI. You will get a 500 when you do and won't know about it until it happens because it is a runtime not compile time error. This script will crash 50% of the time:

sub cleaner { $_[0] =~ s/foo/bar/; } if ( rand > 0.5 ) { cleaner('foo') } __DATA__ Modification of a read-only value attempted at script line 1. # someti +mes
cheers

tachyon

s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Replies are listed 'Best First'.
Re: Re: Re: Re: Re: Problem creating a function
by IlyaM (Parson) on Dec 25, 2002 at 16:06 UTC
    <sarcasm>
    Using die is bad practice. Here is an example. If you use it you will get a 500 when you do and won't know about it until it happens because it is a runtime not compile time error. This script will crash 50% of the time:
    if ( rand > 0.5 ) { die "foo" }
    </sarcasm>

    Seriously what is your point? You can cause runtime errors with many Perl constructs and it doesn't necessary mean that using them is a bad practice. OUT parameters is a powerful language feature when used wisely.

    --
    Ilya Martynov, ilya@iponweb.net
    CTO IPonWEB (UK) Ltd
    Quality Perl Programming and Unix Support UK managed @ offshore prices - http://www.iponweb.net
    Personal website - http://martynov.org

      I never use die in CGI. I use a custom die_nice() routine which you will see dozens of references to if you do a Super Search for 'tachyon die_nice'. This is not a CGI, this is a demo snippet to illustrate a point so using die is perfectly appropriate. Your sarcasm is wasted.

      Presenting OUT parameters to someone (obviously very inexperienced) with a "this is an OK way to do it" and not mentioning the problem I noted is sub optimal IMHO. You know that they will probably use the code verbatim.....

      If you use OUT parameters much you will get caught passing constants to them. These bugs may not immediatly be obvious. You avoid this problem by not using them. I would be interested to see a good example of where they are a powerful and indespensible language feature given that you can easily pass references to and from subs.

      If you are doing a code review which is easer to understand without looking at cleaner()

      # for sub cleaner { my $var = shift; $var =~ s/foo/bar/; $var } my $var = cleaner($var); # then maybe lines later... print $var # or in a single line print cleaner($var); # or this if you have sub cleaner { $_[0] =~ s/foo/bar/ } cleaner($var); # then maybe lines later... print $var; # and you can't print cleaner($var) # unless you have sub cleaner { $_[0] =~ s/foo/bar; $_[0] }

      cheers

      tachyon

      s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

        One good example which comes to my mind is a helper subroutine I wrote for a test suite of one of my modules. Simply put that module has a subrotuine which given a set of input parameters can generate some output. In the test suite the helper subroutine wraps this call and compares the output with some file. If it matches the test is passed and if it doesn't it is not passed. The problem I had is that it in some cases it was ok for the output to vary slightly (for example it could contain current datatime or module version which change with time). So I had to use callback subroutine which cleaned up the output before comparing with the file.

        Now compare:

        # using OUT parameters run_test(params => \%params, filename => 't/foo/bar', cleanup => sub { $_[0] =~ s/foo/bar/ }); # not using OUT parameters run_test(params => \%params, filename => 't/foo/bar', cleanup => sub { my $var = shift; $var =~ s/foo/bar/; $var }) +;
        To my taste first version is much cleaner.

        As for my sarcasm. Probably it was wasted and I'd better to reword it to express myself better. The thing is that for any dynamical language like Perl runtime errors is a norm so I simply cannot accept argument that feature which might cause runtime error is a bad.

        --
        Ilya Martynov, ilya@iponweb.net
        CTO IPonWEB (UK) Ltd
        Quality Perl Programming and Unix Support UK managed @ offshore prices - http://www.iponweb.net
        Personal website - http://martynov.org

        If you use OUT parameters much you will get caught passing constants to them.
        Perhaps, as a general rule. (It is Murphy's Law, after all.) But I highly doubt that someone is going to try to use this cleaner() to clean up a string of literal HTML.
        These bugs may not immediately be obvious. You avoid this problem by not using them.
        You avoid this problem by paying attention to the caveats on the API. If the doco says "Don't pass a constant", don't pass a constant. If the doco says "This function throws an exception on error", then you wrap the call with eval{}. (Or allow that your program may abort.)
        ... given that you can easily pass references to and from subs.
        And why do references make any difference? (Hint: they don't.)
        cleaner( \"to be cleaned" ); sub cleaner { my $ref = shift; $$ref =~ s/foo/bar/; }
        results in the same error: Modification of read-only value attempted.

        jdporter
        ...porque es dificil estar guapo y blanco.

Re: Re: Re: Re: Re: Problem creating a function
by jdporter (Paladin) on Dec 27, 2002 at 04:55 UTC
    It may crash 50% of the time, but it only takes one crash to alert the programmer to her misuse of the function. It's incumbent on the programmer to know how to call the API correctly. Especially if it's her own.

    The simple fact is that perl is a dynamic language, and provides many essential features that can only be fully realized at "run time". That means run time errors (i.e. exceptions) are going to happen, you can count on it, and if you're a half-way careful programmer, you're going to prepare for them to happen. If the fact that your program is a CGI makes this preparation a little more difficult, well then, tough. Deal with it. Trap $SIG{__DIE__} if you have to. But don't forbid run-time exceptions, because you can't anyway. What does   $foo->bar; do? There are several possibilities, including Can't locate object method "bar", and none of them can be caught at compile time. That's just the nature of the beast (Perl).

    jdporter
    ...porque es dificil estar guapo y blanco.