The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

P, Pe - Safer, friendlier sprintf/printf+say

VERSION

Version "1.0.20"

SYNOPSIS

  P FILEHANDLE, FORMAT, LIST
  P FORMAT, LIST
  P @ARRAY
  $s=P @ARRAY; P $s;          # same output as "P @
  Pe                          # same as P, but output to  STDERR

P is a combined printf, sprintf & say in 1 routine . It was designed to save on typing and undef checking when printing strings. It saves on in that you don't have constantly insert or move newlines (\n). If you change a string into a formatted string, insert P, as in:

  die "Wrong number of params";
             # to
  die P "Expecting 2 params, got %s", scalar @ARGV;

When printed as strings ("%s"), undefs are automatically caught and "(undef)" is printed in place of Use of uninitialized value $x in xxx at -e line z. P knows how to print simple references and does so automatically. Instead of HASH=(0x235432), at the first two¹ levels, it will print the contents of the hash: {none=>0, one=>1, two=>2}. Meant for use in development and as debug aid. Made executable and run, it does a small self-demo/test. Pod-documentation also builtin.

¹-two was chosen so that the first level of the interior of an object could be printed, as the first reference is to the object itself.

DESCRIPTION

While designed to speed up and simplify development, isn't limited to such.

It automatically handles newlines at the end of output, letting the user ignore an LF at the end of a line (present or not).

The auto-newline feature at the end of a line can be supressed by adding the Unicode control char "Don't break here" (0x83) at the end of a string, but be warned, in normal ourput, lines are line buffered and the I/O system won't flush the output until it sees the end-of-line.

Blessed objects, by default, are printed with a short label at the front. This means the output is NOT, at this time, by default, valid perl code. Compactness takes precidence over language semantics. Note that these default when printing objects via "%s". Printing something other than a reference will print (or format) the object the same way that printf or sprintf would.

A difference between P and sprintf, paraphrasing and contrasting the sprintf documentation: Like printf, P follows the perl design philosophy and tries to "Do what you mean" when you pass it array as your first argument. The array is NOT given scalar context and instead of trying to use the size of the array as a format (which is almost never useful), it will use the first element of the array as the format specification by which to format the rest of the arguments. This is the same behavior of printf and fixes a wart in the language. It also, can automatically be used as a replacement for "say", as it auto-appends the needed LineFeed at the end of line. It will NOT append a line feed to the formatted output if it is assigned to a variable.

NOTE: this has the, sometimes, surprising effect of silencing P when you might not expect it: if it is the last statement in a subroutine, P will assume that you want to return the formatted string as the value of the subroutine or function.

Experimental Feature

While P is normally called procedurally, and not as an object, there are some rare cases where you would really like it to print just 1 level deeper. In such cases, to pass options to P, you need an object handle to it's ops routine to which you can pass a depth parameter.

Example

Suppose you had an array of objects, and you wanted to see the contents of the objects in the array. Normally P would only print the first level -- being the contents of the array:

  my %complex_probs = (                                
      questions =E<gt> [ "sqrt(-4)",  "(1-i)**2"     ],
      answers   =E<gt> [ {real => 0, i =>2 }, 
                     {real => 0, i => -2 } ] );
  P "my probs = %s", \%complex_probs;

Would normally produce:

  my probs = {questions=>["sqrt(-4)", "(1-i)**2"], answers=>["HASH(0x235efc0)", "HASH(0x235f098)"]} 

When you might want to see those hashes as they are short anyway. To do that you'd use the object and print with that, like this:

  my %complex_probs = (                                     
      questions => [ "sqrt(-4)",          "(1-i)**2"     ],
      answers   => [ {real => 0, i =>2 }, { real => 0, i => -2 } ] );
  my $p=P::->ops({depth=>3});                                
  $p->P("my array = %s", \%complex_probs);

Which produces:

  my array = {questions=["sqrt(-4)", "(1-i)**2"], answers=>[{i=>2, real=>0}, {i=>-2, real=>0}]}

Note: Don't confuse P::P with a Pretty Printer or Data::Dumper. Especially, when printing references, it was designed as a debug aid.

MORE EXAMPLES

  P "Hello %s", "World";        # auto NL when to a FH
  P "Hello \x83"; P "World";    # \x83: suppress auto-NL to FH's 
  $s = P "%s", "Hello %s";      # not needed if printing to string 
  P $s, "World";                # still prints "Hello World" 

  @a = ("%s", "my string");     # using array, fmt as 1st arg 
  P @a;

  @a = ("Hello %s", "World");   # format in array[0]
  P @a;
  P @a;                         # prints 1st of @a elements (Hello %s)
  P 0 + @a;                     # prints #items in 'a'

  P "a=%s", \@a;                # prints contents of 'a': [1,2,3...]

  P STDERR, @a                  # use @a as args to a specific FH
                                # NOTE: "," after FH 
  Pe  "Output to STDERR"        # 'Shortcut' for P to STDERR

  # P Hash bucket usage + contents with hashes
  %H=(one=>1, two=>2, u=>undef);

  P "%H #items %s", 0+%H;       # Show number of  items in hash
  P "%H hash usage: %s", "".%H; # Shows used/total Hash bucket usage
  P "%H=%s", \%H;               # Show contents of hash:
    %H={u=>(undef), one=>1, two=>2}

  bless my $h=\%H, 'Hclass';    # Blessed objs... 
  P "Obj-h = %s", $h;        #     & content:
    Obj-h = Hclass{u=>(undef), one=>1, two=>2}

NOTES

Values given as args with a format statement, are checked for undef and have "(undef)" substituted for undefined values. If you print vars as in decimal or floating point, they'll likely show up as 0, which doesn't stand out as well as "(undef)",

While usable in any code, it's use was designed to save typing, time and work of undef checking, newline handling, and doing the right thing with the given input. It may not be suitable where speed is important.