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) {
...
}
DBI-related Stuff
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).