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

NAME

PlusPlus - [Delphi|VB|Java]-like Perl preprocessor

SYNOPSIS

  ### Case 1: plain script

  use PlusPlus;
  
  /*
        This is 
        a long awaited
        multiline
        comment
  */
  
  my $nested_hash = {outer => {inner => {a => 1, b => [19, 73], c => 3}}}
  
  $nested_hash.outer.inner.a = 5;      # colon in variable names
  $nested_hash.outer.inner.b.[1] = 37; 
  
  $dbh.do ("DROP DATABASE TEST");      # colon in method names
  
  with ($nested_hash.outer.inner) {    # 'with' operator
      ($.a, $.c) = (10, 30);
      print " b[0] = $.b.[0]\n";
  };
  
  function f ($x, $y = 0) {            # named parameters and default values
      return sin ($x) * cos ($y)
  };
  
  ### Case 2: working with a database
  
  use PlusPlus;
  use DBI;
  
  my $dbh = DBI -> connect ($dsn, $user, $password);

  select name, phone from staff where salary between ? and ? -> my $sth;
  
  forsql $sth (1000, 1500) {
      print "<tr>   <td> $.name </td>  <td> $.phone </td>  </tr>"
  }
  
  
  ### Case 3: procedural module
  
  use PlusPlus;
  
  module Child (Ancestor::Mother, Ancestor::Father);  
  
            sub foo { ... };           # not exported
  
  export    sub bar { ... };           # exported by default
  
  export_ok sub baz { ... };           # can be imported explicitly
  
  
  ### Case 4: class

  class Child (Ancestor::Mother, Ancestor::Father);  

  method init {                        # constructor callback
      ($.x, $.y) = (10, 3);
  }
  
  method diag {                        # some method
      sqrt ($.x * $.x + $.y * $.y)
  }

  method do_it_to_me ($coderef) {      # one more method
      &$coderef ($self);
  }
  
  getter fldname {                     # getter method
      print "They asked my value!\n";
      return $.fldname;
  }

  setter fldname ($value) {            # setter method
      $.setting_counter ++;  
      $.fldname = $value;
  }

DESCRIPTION

PlusPlus is a quick hack providing many features that are to be implemented in Perl6 but a lot of people would use right now.

PlusPlus is a preprocessor based on the Filter distribution available from CPAN. It alters the standard Perl synax transparently: you don't need to recompile the interpreter or launch your scripts in some specific way. All you need is to install Filter - and

 use PlusPlus;

'.' instead of '-> {}'

Using PlusPlus, you can dramatically clearify your code by typing

    $foo.bar.[$i].baz
    

each time instead of

    $foo -> {bar} -> [$i] -> {baz}

Yes, of course, the colon means the concatenation. So, you might suppose a collision in case like

    $foo.$bar
    

What would it be: "$foo.$bar" or $foo-{$bar}>? Please, remind: when using PlusPlus, always type at least one space aside of your concatenation colon. So,

    $foo.$bar      eq  $foo->{$bar}
    $foo . $bar    eq  "$foo$bar"

And what about the method calls? It's very similar (see SYNOPSYS). But, note: the method call must be followed by an open paranthesis, even if the argument list is void.

    $st.finish     eq  $st -> {finish}
    $st.finish ()  eq  $st -> finish ()

WITH statement

The PlusPlus preprocessor introduces the with statement in the manner similar to Borland (C) Delphi (R) and MS ($) VB (...). Each fragment of code like

    with ($foo) {
        ...
    };

is mapped to

    do { my $__with__prefix__ = ($foo);
        ...
    };
    

All variables like $.bar are renamed to $__with__prefix__.bar. It is very unprobably that you use the variable named $__with__prefix__, but, in any case, you are warned.

And, please, don't forget to put a semicolon after the closing brace: with is do, not while.

Named args

As you know, there is whole a lot of ways to access argument values passed to a sub from within its body (shift, $_[$n]...). But usually you write a sub that receive a predefined set of args that you want to access by name. In this case, your code looks like

    sub mySub {
        my ($arg1, $arg2, @all_other) = @_;
        ...
    }

With PlusPlus, you can obtain the same with

    function mySub ($arg1, $arg2, @all_other) {
        ...
    }
    

Moreover, often some of parameters have default values to be set if an undef is passed as argument. Using not PlusPlus, you make something like

    sub mySub {
        my ($arg1, $arg2, $arg3, @all_other) = @_;
        $arg2 = 2 unless defined ($arg2);
        $arg3 ||= 3;
        ...
    }
    

With PlusPlus:

    function mySub ($arg1, $arg2 = 2, $arg3 = 3, @all_other) {
        ...
    }

When using DBI, it's very usual to code like this:

    $sth -> execute ($arg1, $arg2);
    while (my $hash_ref = $sth -> fetchrow_hashref) {
        do_somthing ($hash_ref -> {a}, $hash_ref -> {b})
    }

OK, it's really nice (when comparing to JDBC :-), but with PlusPlus you can express yourself a little bit cleaner:

    forsql $sth ($arg1, $arg2) {
        do_somthing ($.a, $.b)
    }

Simple, isn't it? But it is not all. PlusPlus allows to use pretty plain SQL in your perl scripts. The source line

    SELECT * FROM foo WHERE id = 6535 -> my $sth;
    

is mapped to

    my $sth = $dbh -> prepare ("SELECT * FROM foo WHERE id = 6535");
    

The $dbh name is hardcoded, sorry. Currently only SELECT statements are allowed.

Procedural Modules

PlusPlus simplifies the creation of Perl modules. You don't need to use Export.pm explicitly nor fill manually @ISA, @EXPORT and @EXPORT_OK arrays.

The string

  module Child (Ancestor::Mother, Ancestor::Father);  

is mapped to

  package Child; use Exporter; use vars qw(\@ISA \@EXPORT \@EXPORT_OK);    

Moreover, the last (additional) line of your source will contain the needed @ISA expression.

You can add a modifier export or export_ok to any sub, then its name will appear in @EXPORT or @EXPORT_OK list at the end of source.

And, finally, you don't ever need to put a 1; after all: it is done automatically.

Classes

PlusPlus provides a simple OO-syntax addon to the Perl interpreter. The string like

  class MyObject (Ancestor::Mother, Ancestor::Father);  

does the same thing as the module statement described above, but creates a standard constructor called new that blesses a void anonymous hashref. Now you can create the appropriate objects with expressions like

  my $object = new MyObject ('blah', "blah");

in any script that uses your module.

PlusPlus introduces a special kind of sub for class modules: methods. The source

  method do_it ($x, $y, @foo) {
    ...
  }  

is mapped to

  sub do_it { my $self = shift; my $__with__prefix__ = $self; my ($x, $y, @foo) = @_;
    ...  
  }

The metod named init is called by the constructor new with the arglist passed to it.

Quasimembers

From the OO point of view, explicit use of class members is not good practice. In theory, you'd never access to object's fields but always call appropriate getter/setter methods when you want to obtain/change its values. Good OO programming languages have some special syntax that allows an implicit binding of getters/setters to some fake class members. (I mean the Borland Delphi's feature called 'properties'). PlusPlus have something similar.

Suppose you want to have some side effect when the field bar of an instance of class Foo changes. Write

  class Foo;
  
  setter bar ($value) { 
      print "And now bar = $value\n"; # side effect
      $.bar = $value;
  }
  

Now, if $foo is an instance of Foo, a statement

      $foo.bar = 666;
      

will dump the message

      And now bar = 666
      

to the stdout. If you're afraid of some kind of numbers or just want to overload the getting procedure, add a getter method:

  getter bar {  
      return $.bar == 666 ? 'Oh no!' : $.bar;
  }

AUTHOR

D. E. Ovsyanko, do@rambler.ru

SEE ALSO

Filter(3).