I have a set of methods where I would like the caller to be able to override a value, or it defaults to the instance variable.
So what I keep trying to do is:
method foo( Str :$blah = $self->blah ) {
#doStuff
}
which throws a parsing error so I end up doing this everywhere
method foo( Str :$blah? ) {
$blah = $self->blah unless defined $blah;
#doStuff
}
Not horrendous, but seems silly when MooseX::Method::Signatures supports the default concept and has fixed all my other standard 'start of method' lines.
Invariably when I'm trying to do something like this and I can't find anyone else on the web who's run into the same problems, I'm approaching the problem the wrong way. It seems like I might be trying to jam a functional program into a oo layout, rather than actual oo as the methods are more helper functions for calling externally rather than methods operating on the object. So just checking if I'm just defining it incorrectly or if what I'm doing is "dumb" or just not supported by Parse::Method::Signatures.
AFAIK The Signatures module hooks itself into the Perl parser and injects some code to handle the prototypes. It is remarkable that this works.
That said, using non-constant values as defaults could have issues. And there may be scenarios where calling some code to prepopulate a value could wreak havoc. Specifically, should the code that prepopulates the value should only be called if no value for the argument is given, or should it be always called? What should we do with side effects? What should the caller be? If I have a global $self object, shouldn't that receive the method call, as the scoping rules clearly dictate this? (As our $x=5; my $x=$x; is valid, but just my $x=$x is not). Even better, what would happen if the default value population method call would call the same method, but again without a value for the optional parameter?
You can always fall back to old-school optional parameters:
sub foo {
my ($self, $blah) = #_;
# something like my ($self, $blah) = (#_, $self->blah); wouldn't work, of course.
$blah //= $self->blah; # nicer than old `unless defined`
...;
}
or, in this case:
method foo (:$blah?) {
$blah //= $self->blah
}
I find this use of the defined-or operator quite enjoyable.
Related
I've seen CPAN Perl modules that can be used in a functional or OO way. I usually write OO and Functional packages depending on what I need, but I'm still not how write modules that can used both ways.
Could somebody give me a simple example of a package that can be used in functional and/or OO way? I'm obviously interested in the pieces that allows the package be used both ways.
Thank you
A core example is File::Spec, which has a File::Spec::Functions wrapper. It's not so much object oriented but it does use the object oriented principle of inheritance, so its main API uses method calls, but it doesn't need to keep any state.
use strict;
use warnings;
use File::Spec;
use File::Spec::Functions 'catfile';
print File::Spec->catfile('/', 'foo', 'bar');
print catfile '/', 'foo', 'bar';
Another example is Sereal, whose encoder and decoder can be used both as objects or via exported functions which wrap them.
use strict;
use warnings;
use Sereal::Encoder 'encode_sereal';
my $data = {foo => 'bar'};
my $encoded = Sereal::Encoder->new->encode($data);
my $encoded = encode_sereal $data;
Sereal aside, it's usually good organizational practice to keep your object classes and your exporting modules separate. Especially don't try to have the same function be callable as a method or an exported function; the primary issue is that it's indistinguishable from the subroutine itself whether it was called as $obj->function('foo') or function($obj, 'foo'). As #choroba noted, CGI.pm tries to do this and it's a mess.
My WiringPi::API distribution is written in such a way. Note that in this case here, there's no state saving required, so if keeping state is a necessity, this way of doing it won't work as-is.
You can use it functionally:
use WiringPi::API qw(:all)
setup_gpio();
...
Or use its Object Oriented interface:
use WiringPi::API;
my $api = WiringPi::API->new;
$api->setup_gpio();
...
For functional, I use #EXPORT_OK, so that the user's namespace isn't polluted unnecessarily:
our #EXPORT_OK;
#EXPORT_OK = (#wpi_c_functions, #wpi_perl_functions);
our %EXPORT_TAGS;
$EXPORT_TAGS{wiringPi} = [#wpi_c_functions];
$EXPORT_TAGS{perl} = [#wpi_perl_functions];
$EXPORT_TAGS{all} = [#wpi_c_functions, #wpi_perl_functions];
...and a few example functions/methods. Essentially, we check the number of parameters coming in, and if there's an extra one (which would be the class/object), we manually just shift it out:
sub serial_open {
shift if #_ > 2;
my ($dev_ptr, $baud) = #_;
my $fd = serialOpen($dev_ptr, $baud);
die "could not open serial device $dev_ptr\n" if $fd == -1;
return $fd;
}
sub serial_close {
shift if #_ > 1;
my ($fd) = #_;
serialClose($fd);
}
sub serial_flush {
shift if #_ > 1;
my ($fd) = #_;
serialFlush($fd);
}
Typically I would do some parameter checking to ensure that we're shifting off the correct thing, but in testing, it was faster to allow the back end C/XS code worry about that for me.
As stated, there are a number of modules that do this and some have been named. A good practice is to write a separate module for the functional interface, that uses the class and exports its (select) functions.
But it is quite possible to have both interfaces in one package, with same method/function names, if there is a specific need for that. See the section at the end for one very specific and rare use case that wouldn't be handled by the following basic example, and for how to resolve it.
Here is a basic package that has both interfaces
package Duplicious; # having interfaces to two paradigms may be confusing
use warnings;
use strict;
use feature 'say';
use Scalar::Util qw(blessed);
use Exporter qw(import);
our #EXPORT_OK = qw(f1);
my $obj_cache; # so repeated function calls don't run constructor
sub new {
my ($class, %args) = #_;
return bless { }, $class;
}
sub f1 {
say "\targs in f1: ", join ', ', #_; # see how we are called
my $self = shift;
# Functional interface
# (first argument not object or class name in this or derived class)
if ( not ( (blessed($self) and $self->isa(__PACKAGE__))
or (not ref $self and $self->isa(__PACKAGE__)) ) )
{
return ($obj_cache || __PACKAGE__->new)->f1($self, #_);
}
# Now method definition goes
# ...
return 23;
}
1;
The caller
use warnings; # DEMO only --
use strict; # Please don't mix uses in the same program
use feature 'say';
use Duplicious qw(f1);
my $obj = Duplicious->new;
say "Call as class method: ";
Duplicious->f1("called as class method");
say "Call as method:";
my $ret_meth = $obj->f1({}, "called as method");
say "\nCall as function:";
my $ret_func = f1({}, "called as function");
Output
Call as class method:
args in f1: Duplicious, called as class method
Call as method:
args in f1: Duplicious=HASH(0x21b1b48), HASH(0x21a8738), called as method
Call as function:
args in f1: HASH(0x21a8720), called as function
args in f1: Duplicious=HASH(0x218ba68), HASH(0x21a8720), called as function
The function call dispatches to the method, thus two lines (note arguments).
I find it in principle awkward to use Exporter in a module that defines a class (but I am not aware of any actual problems with doing it); it results in a potentially confusing interface. This on its own is a good reason to separate interfaces so that the functional one has to load a specific module.
There is also one detail that requires attention. The method call
($obj_cache || __PACKAGE__->new)->f1(...)
uses the cached $obj_cache (if this sub has been called already) to make the call. Thus the object's state is kept, that may or not have been manipulated in the previous calls to f1.
That is rather non-trivial in a call meant to be used in a non object-oriented context and should be carefully investigated. If there are issues just drop that cacheing or expand it into a full if statement where the state can be reset as needed.
These two uses should absolutely not be mixed in the same program.
To test with a derived class I use the minimal
package NextDupl;
use warnings;
use strict;
use feature 'say';
use parent 'Duplicious';
1;
and add to the main program above the following
# Test with a subclass (derived, inherited class)
my $inh = NextDupl->new;
say "\nCall as method of derived class";
$inh->f1("called as method of derived class");
# Retrieve with UNIVERSAL::can() from parent to use by subclass
my $rc_orig = Duplicious->can('f1');
say "\nCall via coderef pulled from parent, by derived class";
NextDupl->$rc_orig("called via coderef of parent by derived class");
The additional output is
Call as method of derived class
args in f1: NextDupl=HASH(0x11ac720), called as method of derived class
Call via coderef pulled from parent, by derived class
args in f1: NextDupl, called via coderef of parent by derived clas
This incorporates a test using UNIVERSAL::can, as it came up in a comment.
There is one specific limitation (that I am aware of), raised and discussed in comments.
Imagine that we write a method that takes an object (or a class name) as its first argument, so to be invoked as ->func($obj); further – and this is what matters – this method allows any class as it works in a way that doesn't care what class it has. This would be very particular, but it is possible and it raises the following problem.
The function call corresponding to this method would be func($obj), and when $obj happens to be in the hierarchy of this class that would result in the method call ->func(), incorrectly.
There is no way to disambiguate this in the code that decides on whether
it's called as a function or as a method, since all it does is it looks at the first argument. If it's an object/class in our own hierarchy it decides that this was a method call on that object (or a class method call), and in this particular case that is wrong.
There are two simple ways, and possibly another one, for the module's author to settle this
Do not provide the functional interface for this highly specific method
Give it a separate (clearly related) name
The if condition that decides how we are called, by checking the first argument, is canned but still written for every method that has that interface. So in this method check one more argument: if the first one is object/class of this class and the next is (any) object/class then it's a method call. This does not work if that second argument is optional.
All this is completely reasonable. In a class that exercises its defining trait, to have and use data ("attributes"), there will likely be methods that cannot be translated into function calls. This is because a single program should only use one interface, and with functions there is no state so methods that rely on it won't fly. (Use of a cached object for this is highly treacherous.)
So one will always have to decide carefully about the interface, and to pick and choose.
Thanks to Grinnz for comments.
Note that there is a completely different paradigm of "functional programming," and the title leaves that a little unclear. All this is about the functional interface in a procedural approach.
I'm using CoffeeScript to create a class and build a private method, but my code feels kludgy.
As in the example below, first I define the method with = and then I am forced to use the call method on the portion to be used. But this seems like a kludgy workaround, so I want to know if there is a cleaner solution.
class Human
constructor: (#name, #height, #weight) ->
_realWeight = ->
#weight
answerWeight: ->
console.log(_realWeight.call(#) - 5)
$ ->
ken = new Human('Ken', 165, 70)
ken.answerWeight()
TL;DR
No.
Longer Answer
There is only one way to have truly private data in javascript/coffeescript: closures.
First, lets consider some alternatives:
Symbols
Because symbols are unique they can be used to create psuedo-private data:
you can only access the property if you have a reference to the symbol its keyed to:
foo = Symbol('I am unique')
bar = {}
bar[foo] = "I am almost private"
Code that doesn't have access to foo can't easily get to that property of bar except for Object.getOwnPropertySymbols. So not easy to break, but breakable.
Underscores
Typical naming convention says that properties/methods prefixed or followed by an underscore are 'private', they are not to be used by an external caller. However, that 'privacy' is not in any way enforced by the runtime.
So lets talk about closures.
Simple Closure example
makeFoo = (something) -> getSomething: -> something
foo = makeFoo(3)
foo.something # undefined
foo.getSomething() # 3
Now there is no way to get at the parameter passed to the constructor except to call the method. This pattern, while slightly more elegant in coffeescript, is still kinda lame. Lots of duplicated function objects. Not so bad for just getSomething, but add a bunch of methods and it gets ugly fast. Also, typically not as easily optimized by the JIT compiler as foo = new Foo() would be. Fortunately, ES 2015 to the rescue:
Advanced Closure Example
Foo = null
do ->
privateData = new WeakMap()
getSomething = -> privateData.get(this)
Foo = class Foo
constructor: (something) -> privateData.set(this, something)
getSomething: getSomething
foo = new Foo(3)
foo.something # undefined
foo.getSomething() # 3
new Foo(42).getSomething() # 42
foo instanceof Foo # true
Now all instances of Foo share one copy of getSomething rather than each getting their own. The weakmap is hidden in the closure created by the IIFE, and because of the 'weak' part of WeakMap when the instance gets garbage collected the private data will be as well. You are also now potentially able to enjoy the benefits of the compiler optimizing newly created objects. Last but not least, instanceof still works properly (to the extent that it ever works properly).
Further reading.
Even More reading
Note
WeakMaps are not supported in all browsers (for IE its 11 or bust). There is a shim, but it cannot be completely polyfilled. Whether or not the shim gets close enough is a call you'll have to make.
Should instance methods in Perl call each other like this:
package BlaBla;
sub foo {
my($self) = #_;
#do something awesome;
}
sub bar {
my($self) = #_;
foo();
}
Or like this:
package BlaBla;
sub foo {
my($self) = #_;
#do something awesome
}
sub bar {
my($self) = #_;
$self->foo();
}
Thank you all for your time.
Yes, you should include $self - if you don't, polymorphism won't work because each method will look for all calls in its own package, even if they're overridden in a subclass. Worse, if the referenced method is inherited from a parent and not overridden in the current subclass, the program will die because it doesn't exist in that package. And that's even if you do remember to try to fake out Perl's OO mechanism by passing $self as the first parameter.
If foo() is a method that can be called from other places you should certainly always call it as a method, otherwise classes inheriting from you won't be able to override it, and you'll force your foo() to check if it's being called in a methody-way or in a functiony-way.
On the other hand, if foo() is just some helper code that a few of your methods use, and is quite specific to your implementation of the class, then you can call it directly, but should then really always call it directly, and might want to label it as a private function available to the class by prefixing its name with an underscore: _foo().
The first one won't work, assuming you use $self somewhere in foo(), because it's not getting any arguments passed. You could call foo($self), but you're almost certainly better off using actual method call syntax instead of throwing the OO features of Perl out the window and just treating foo() as a function that happens to call its first parameter "$self".
Yes, instance methods should call each other with $self - otherwise, in some cases you'll need to check the args of the method and figure out whether it's being called on $self or not, which will make your code messier for no reason.
Th first approach will not work as written.
sub bar {
my($self) = #_;
foo();
}
Here you are explicitly invoking foo as a function with no arguments via that foo(); statement. This will construct an empty local #_ array. The first statement in foo extracts $self as the first element from this local #_, so $self is undefined with this mechanism.
You need to pass $self as an argument to foo. There are (at least) five ways to do this:
Arrow notation: Invoke foo via $self->foo();
Indirect notation: Invoke foo via foo $self;
Normal subroutine invocation: Invoke foo via foo($self);
Implied arguments: Invoke foo via foo $self; This option can only used if foo has been predeclared with a function prototype.
Don't construct that local #_ array. Let foo piggyback on bar's #_ array. Invoke foo via &foo; Note that there are no parentheses in this invocation.
Regarding option #5: It does exist. Don't use it. It will get you into trouble.
The difference between #2 and #4 become apparent when foo takes additional arguments. The indirect notation becomes (for example) foo $self 42; while the implied form becomes foo $self, 42; The indirect notation (option 2) is now strongly discouraged. Options 3 and 4 are also discouraged for use with methods.
That leaves option #1. Even though the arrow notation is just syntactic sugar, it means a lot to the reader. Use it.
Normally, to call a method from its reference, it should go something like below:
$methodref->(#args)
But when invoke a method from its reference returned from "can", it seems inconsistent.
$methodref = $my_obj->can(my_method);
$my_obj->$methodref(#args) if $methodref; # why it isn't $my_obj->$methodref->(#args)?
Can someone please shed some light on this?
Thanks,
CC
The reason is that the object has to be the first thing passed in to the function. This is automatically done for you if you make a method call. But $methodref->($my_obj, #args) will also work.
The CODE ref returned by can doesn’t have an object associated with it once that can is done. That’s why you still need to use an object as an invocant.
Note that this is dangerous, because there is no longer any guarantee that this is method that is supposed to be called on that object. I suppose you might do something like this:
$objmethref = $my_obj->can("methname") && sub { $my_obj->methname(#_) };
# then later
$objmethref->(#args);
but I’m not sure what it is you really want to do.
$my_obj->$methodref->(#args)
is
( $my_obj->$methodref() )->(#args)
In other words, it would call the method with no args, and attempt to use the result as a function reference. It's not what you want at all
The obvious means of calling it is
$methodref->($my_obj, #args)
but Perl provides a syntax that looks like a method-call for your pleasure.
$my_obj->$methodref(#args)
$methodref->(#args) is a function call, not a method call, so won't have the object automatically passed.
$my_obj->$methodref->(#args) would call $methodref with no parameters other than the object parameter, and use its return value as a coderef, calling that and passing it the indicated args.
I noticed that when you call a superclass's methods, you need to do something like this :
my $self = $class->SUPER::new();
Why isn't that:
my $self = $class->SUPER->new();
I suspect because $class->SUPER->new() would normally be the same as $class->SUPER()->new(). But there isn't a $class->SUPER() function, and its not clear what that would return.
On the other hand, $class->Foo::Bar has always been a valid way to call a method directly by full name, so making a special package-like thing — SUPER — fits in better. (I suspect that you could actually implement SUPER as a package, and maybe it historically was, I don't know)
PS: Take a look at the mro package, and $self->next::method. Also, take a look at Moose if you're going to do serious OO work in Perl.
In short, SUPER isn't a method. It's a virtual package. It's documented in perlobj under the "Method Invocation" section.
Note, however, that SUPER bases itself on the current package, not the package of the instance you used it with.
Method calls have a number of forms:
Calls method, possibly inherited:
->method()
Explicitly calls sub Package::method, whether that's in the inheritance tree or not:
->Package::method()
Explicitly calls the referred-to sub, whether that's in the inheritance tree or not:
->$coderef()
Calls the method that would have been called by __PACKAGE__->method() if there were no sub method in __PACKAGE__ (N.B. the class or object on the left of -> is irrelevant):
->SUPER::method()
Any of the above, depending on the contents of $method:
->$method()
(Legal even under use strict;.)
While the first form is the most common, it's worth learning about the others and how they work.
To add to what derobert said:
You're calling 'new' in the 'SUPER' namespace but passing it the object (or string), '$class'.
You don't have to use SUPER, as you can give the full package name of the parent (useful in cases of diamond inheritance):
sub init {
my $self = shift;
$self->ParentClass1::init();
$self->ParentClass2::init();
}