janert has asked for the wisdom of the Perl Monks concerning the following question:

Question (short version): Should a function, which requires numerical arguments, validate its inputs? If so, how?

Question (long version): Assuming you write a function, which takes a numeric argument. Should this function validate its input and warn/fail if a non-numeric value is provided?

The built-in functions do not do this - they rely on implicit numeric conversion. For instance, sin("foo") evaluates to 0 (=sin(0)), and cos("3.1415bar") evaluates to -0.99999 (ie to -1 =cos(pi)).

This may be ok for functions that return immediately, and without side effects. But what about an object, that collects values, to perform some calculation later:

for( @data ) {
  $s->add_data( $_ );
}
print $s->average();

Would it not be useful to be warned early (ie. as the data is added) if garbage is passed in?

The argument can be put forward that implicit typ conversion by the function is a good thing, and that it is up to the calling code to perform any validation, if desired. However, what makes this question tricky is that there is a very similar problem, where input validation must occur, namely if the function is only defined for a certain parameter range. For example, any implementation of the logarithm must validate that its input is strictly greater than 0. But this seems inconsistent: we validate that the input is legal, but after relying on implicit type conversion. Would it not be better if both forms of validation (input is formally correct as "number") and is mathematically correct (within the range of validity) are performed together? In particular for an accumulating object, similar to the code snippet above?

I am really quite uncertain - I can find reasons to go with either version. I have not found any discussion/recommendation on this point elsewhere. What do others think?

(The strongest argument I can think of is to "do as the built-ins do", that is: convert implicitly, and only then validate the parameter range if necessary. Is this the general consensus?)

Replies are listed 'Best First'.
Re: Parameter validation for numeric function arguments?
by ikegami (Patriarch) on Aug 20, 2011 at 22:47 UTC

    Some factors to consider:

    • Is the function part of a public interface?
    • Is the function only used in a single project?
    • How likely is it that an incorrect argument is provided?
    • What are the consequences of receiving bad arguments?
    • Does the function fail safe or fail hard??

    Should this function validate its input and warn/fail if a non-numeric value is provided? The built-in functions do not do this

    Actually, they do.

    >perl -wE"say sin('foo')" Argument "foo" isn't numeric in sin at -e line 1. 0 >perl -wE"say cos('3.1415bar')" Argument "3.1415bar" isn't numeric in cos at -e line 1. -0.999999995707656

      Thanks to everyone who has chimed in.

      What I am taking away here is this:

      • We all agree that input validation is desirable...
      • ... but the way to do it is via warnings, which can be switched on/off using use warnings; or the -w flag. (Inspect the $^W variable in your code to find out.)

      Thanks again, this was helpful.

Re: Parameter validation for numeric function arguments?
by TomDLux (Vicar) on Aug 20, 2011 at 22:36 UTC

    The origin of perl was as a sysadmin tool, and in other situations where people frequently wanted results quickly, and might tolerate a few aberrations if they got the bulk of the results.

    If you want to run a nuclear power plant, or a 747, definitely, validate your inputs.

    If your boss wants you to extract some information from the web logs to see how soon the current heavy load will bring down the web site, take advantage of the fact that '123xyz' in a numeric context is treated as the number 123.

    As Occam said: Entia non sunt multiplicanda praeter necessitatem.

Re: Parameter validation for numeric function arguments?
by toolic (Bishop) on Aug 20, 2011 at 22:21 UTC
    Question (short version): Should a function, which requires numerical arguments, validate its inputs? If so, how?
    Answer (short version): I would want your function to validate my inputs. Most of the time, I want to know ASAP if I have fed the wrong type of thing to a function.

    I can understand your arguments both for and against it. Unless it's a matter of performace (speed), validating is a good thing.

    Again, most of the time, Perl has a knack for Doing The Right Thing. But, on occasion, I have wasted time debugging some code which was too forgiving.

    Scalar::Util::looks_like_number can be used to validate floating-point inputs (I used it in my module).

Re: Parameter validation for numeric function arguments?
by eyepopslikeamosquito (Archbishop) on Aug 21, 2011 at 00:55 UTC