[comp.lang.perl] How about a finicky printf

shaw@paralogics.UUCP (Guy Shaw) (06/23/91)

How about a finicky printf() ?

The Perl implementation of printf() does not do any checking to ensure that
the number of arguments given matches the number called for in the format
string.  Extra arguments are ignored.  Arguments needed beyond the number
given are silently supplied as though a null value were given.  So, the
argument list is, in effect, padded with null values.

  perl -e 'printf "%d %d\n", 1, 2, 3'        =>  1 2
  perl -e 'printf "%d %d\n", 1'              =>  1 0

Awk complains about this at run-time.  Perl ought to be able to complain
at run-time.  I would like to see Perl do awk one better and do a bit
of compile-time analysis, where possible, as well.  Sure, you couldn't
do that for format strings that are variables, and Perl has things like
eval() that can make things a bit trickier; but the majority of times,
in practice, format strings are constants.

If performance degradation is part of the rationale for not doing this
in Perl, then I would suggest doing the checking only when the -w option
is turned on.

Just Another Perl Suggestion from
Just Another Perl Dilettante,
-- 
Guy Shaw
Paralogics
paralogics!shaw@uunet.uu.net  or  uunet!paralogics!shaw

shaw@paralogics.UUCP (Guy Shaw) (06/23/91)

How about finicky arrays?

In article <430@paralogics.UUCP>, I suggested that printf() should be more
strict about its arguments.

>        Extra arguments are ignored.  Arguments needed beyond the number
> given are silently supplied as though a null value were given.  So, the
> argument list is, in effect, padded with null values.

I do not believe that Perl goes to extra work to be so forgiving about
the arguments to printf().  Ignoring extra arguments is easy.  I think
it just doesn't bother to check that there are any extra arguments.
As for the padding of printf's argument list with null values, this
might take extra work in many languages, but in Perl, I think it is
just a natural consequence of the way Perl deals with out-of-bounds rvalue
array references, i.e. silently supply a null value.

So, come to think of it, I wouldn't mind having Perl complain about
out-of-bounds rvalue array refs.  But that brings up two problems.

Problem 1: strict enforcement of array bounds for rvalue array refs
would break existing code.  There is a lot of code out there like

        while($ARGV[0]) { ... shift; }

It wouldn't have been any problem for me to code these things slightly
differently if Perl were strict about array bounds.  But that is
probably part of *The Perl Way*, now.  So, even complaining only
when the -w option is on is no good.

Problem 2: consistency between ordinary array and associative array
semantics.  What about accessing an associative array with a key that
is not in that array?  Isn't that analogous to accessing an ordinary
array with a subscript that isn't in that array - yet?  Well, yes but
the way Perl uses a subscript-like notation for accessing associative
arrays comes form awk.  In an Algol/Pascal/C-like compiled language you
would have functions for accessing associative arrays which provide richer,
though more clumsy notation.  There is a lot more historical precedent
for bounds checking for ordinary arrays with subscript notation.

There has got to be a way of keeping the advantages of simple
subscripting notation and automatic extension of arrays on demand,
without worrying about the grubby low-level bookkeeping details, yet
still get the safety of bounds checking when you want it.

Having said all that ... there are times when I want automatic run-time
bounds checking and times when I do not.  And that may apply to access
of non-existent entries in associative arrays as well as to ordinary
arrays.  So, the behavior ought to be controllable for each array.
Make the default be the way arrays behave now.  Introduce a new perl
function, strict(), such that strict(@array) would make any out-of-bounds
rvalue references to that array cause an exception.  Since this is run-time
stuff, I suppose you could have unstrict(@array), also; but I would tend
to use strict() once up front as a sort of declaration, and would not want
to change the behavior of an array, back and forth.  I would have preferred
that arrays be strict by default, but there's that pesky existing code
problem again.

I would still want assignment to arrays to automatically extend
the array.  The array notation is just too convenient.  But if an array
is strict I think array extension should be restricted to adding on
immediately to the beginning or end without automatically creating
(or failing to complain about) null values for unmentioned subscripts.

Unless I am mistaken about the way Perl is implemented, especially
about the kind of information that is already carried around at run-time
about all arrays, then run-time setting of the strictness of bounds
checking of each array can be done without doing unnatural acts to the
Perl interpreter and without a significant performance penalty.

Afterthought: perhaps an out-of-bounds exception can generate a
pseudo-signal that can be caught.

Just Another Perl Nudge from
Just Another Perl Drudge
-- 
Guy Shaw
Paralogics
paralogics!shaw@uunet.uu.net  or  uunet!paralogics!shaw

tchrist@convex.COM (Tom Christiansen) (06/23/91)

If I want my array bounds checked, I'll do so myself, using the defined()
operator or $# or something else.  Use -w if you're worried about
inappropriately using something before it's defined.  As for printf and
sprintf behaving as they do, this makes it easier to write variatic
functions: sprintf($mask, @args).  Perl is more forgiving that C: if you
blow something, you don't get a coredump, you (usually) just get a null
value.  I happen to like this.

--tom
--
Tom Christiansen		tchrist@convex.com	convex!tchrist
		"So much mail, so little time."  

meissner@osf.org (Michael Meissner) (06/24/91)

In article <1991Jun23.114615.29704@convex.com> tchrist@convex.COM (Tom Christiansen) writes:

| If I want my array bounds checked, I'll do so myself, using the defined()
| operator or $# or something else.  Use -w if you're worried about
| inappropriately using something before it's defined.  As for printf and
| sprintf behaving as they do, this makes it easier to write variatic
| functions: sprintf($mask, @args).  Perl is more forgiving that C: if you
| blow something, you don't get a coredump, you (usually) just get a null
| value.  I happen to like this.

Except the times I have tried -w, the perl library (usually getopt)
gives all sorts of warnings about uninitialized variables.  Sorting
out all of the warnings reminds me of lint....
--
Michael Meissner	email: meissner@osf.org		phone: 617-621-8861
Open Software Foundation, 11 Cambridge Center, Cambridge, MA, 02142

You are in a twisty little passage of standards, all conflicting.