Welcome to Duncan White's Practical Software Development (PSD) Pages.
I'm Duncan White, an experienced and professional programmer, and have been programming for well over 20 years, mainly in C and Perl, although I know many other languages. In that time, despite my best intentions:-), I just can't help learning a thing or two about the practical matters of designing, programming, testing, debugging, running projects etc. Back in 2007, I thought I'd start writing an occasional series of articles, book reviews, more general thoughts etc, all focussing on software development without all the guff.
![]()
Perlstub Part 2: Extending Perlstub to handle object oriented calls
In the Final Part, we'll talk about another Perlstub extension: handling new style function and method syntax
- In the First Part of this article I showed the development of a very simple but useful vi-based editor extension called Perlstub, a simple tool which allowed me to write:
my @nodups = remove_duplicates( @list ); { return @nodups, a list in the same order as the input @list without the duplicates. }press a single key in vi, and have the above transformed automatically into the following Perl function declaration:# # my @nodups = remove_duplicates( @list ); # return @nodups, a list in the same order # as the input @list without the duplicates. # sub remove_duplicates (@) { my( @list ) = @_: # STUB: body goes here. }- Now, in part 2, let's extend Perlstub to handle object oriented calls, as in:
my ($a,$b) = $object->instancemethod( parameters ) my $object = Class->classmethod( parameters )The first is a Perl instance method call to an object, which implies that the corresponding Perl function takes an additional parameter, traditionally called '$self', and the second is a Perl class method call to create an object, which implies that the corresponding function takes an additional '$class' parameter, holding the name of the class. Let's assume that classnames are identified by starting with an upper case letter. Object names will start with anything else - eg. a lowercase letter (as in 'object') or a '$' sigil (as in '$object').- How long would adding method call syntax to perlstub take? Approximately another 10 minutes, I reckon! Having spent a few hours writing this web page up to here, I thought - let's actually develop this useful extension now:
- First, create two new examples, eg4 and eg5, containing a typical instance method and class method example respectively.
- Looking back at our code, when we were parsing the function call example line, we wrote the following:
$func =~ s/\s+//g; # lose all whitespace $func =~ s/^.*=//; # lose any 'thing =' prefix.. # XXX # what's left should look like: wibble(x,y,@z) $func =~ /^(\w+)\(([^)]*)\)$/; ....- At point 'XXX', we were previously expecting something of the form:
wibble(x,y,@z)but now we are expecting any of the following:$object->wibble(x,y,@z) Classname->wibble(x,y,@z) wibble(x,y,@z)To support these new forms, add the following code at point 'XXX':# handle optional "thing->" prefix (method call form) my $ismethod = 0; $ismethod = 1 if $func =~ s/^(.+)->//; my $objorcls = $1 // ""; my $isclass = $objorcls =~ /^[A-Z]/ ? 1 : 0; my $extraparam = $isclass ? '$class' : '$self';And at the end, add:print "debug: ismethod $ismethod, isclass $isclass, extraparam $extraparam\n";- Running this extended code on eg4, we get:
# # my ($a,$b) = $object->instancemethod( parameters ); # instance method call on $object; takes parameters # and return ($a,$b) pair. # debug: func instancemethod(parameters), name instancemethod, params parameters debug: ismethod 1, isclass 0, extraparam $selfand on eg5 (a class method) we get:debug: ismethod 1, isclass 1, extraparam $class- Now, to use our new variables, recall that we had the following parameter splitting code:
my @params; my $protostr = ""; foreach (split( /,/, $params )) # foreach comma separated parameter { s/^/\$/ unless /^[\$@%]/; # prepend $ unless a sigil present push @params, $_; # build up an array of parameters /^(.)/; # extract the parameter's sigil $protostr .= $1; # add it to the prototype string } # YYY my $paramstr = join( ", ", @params ); # join parameters up again print "debug: paramstr=$paramstr, protostr=$protostr\n";At the point marked 'YYY', we add:if( $ismethod ) { unshift @params, $extraparam; # prepend extra leading parameter $protostr =~ s/^/\$/; # and one more leading scalar }- That's all the code we need to add! When we test this with an instance method (eg4) we get:
sub instancemethod ($$) { my( $self, $parameters ) = @_; # STUB: write me... }and the class method (eg5) generates:sub classmethod ($$) { my( $class, $parameters ) = @_; # STUB: write me... }- How much extra code have we had to add? About 15 lines!
d.white@imperial.ac.uk Back to my Practical Software Development Top Page. Written: Jan 2013