Re: Why isn't ->can() curried? (power)
by tye (Sage) on Jan 20, 2003 at 18:21 UTC
|
Because that would be less powerful and slower. Each call to can() would have to create a closure but, in 90% of the cases, it would be almost immediately destroyed.
With the current implementation you can get what you want rather easily. [ This is shown elsewhere in this thead, but please don't override UNIVERSAL::can() as you'll just break other code in some module that is used by some module... that you used. Instead, provide that functionality via a different method name. ] But if your implementation were the default then there would be no easy way to get the current information.
It would no longer work to say
$o1->can($m) == $o2->can($m)
to see if two objects are using the same implementation of a method, for example.
- tye
| [reply] [d/l] |
Re: Why isn't ->can() curried?
by Elian (Parson) on Jan 20, 2003 at 18:18 UTC
|
It isn't curried becausel perl 5 doesn't do currying. That makes things a little tough...
On a more general note, perl 5's OO support is really loose, and very minimalistic. Whether that's a good or bad thing is a matter for a different argument, but it is, nonetheless, true. What you're looking to do, while useful, steps away from that level of minimalism.
It's certainly a reasonable thing to ponder for perl 6, but I'd say at this point perl 5 is awfully far along in its development to change core behaviour like that. And if you were going to do it, you'd really want a full second layer on top of the current base, rather than adding in bits and pieces. While that'd certainly be a good thing, it does mean a bit of extra up-front thought to build that layer so it has some internal consistency.
Having said that, you can always write a module to handle this... :) | [reply] |
Re: Why isn't ->can() curried?
by broquaint (Abbot) on Jan 20, 2003 at 17:17 UTC
|
Would the behaviour be something like this
use strict;
use warnings;
{
my $old_can = *UNIVERSAL::can{CODE};
no warnings 'redefine';
*UNIVERSAL::can = sub {
my($class,$method) = @_;
my $ret = $old_can->($class, $method);
return sub {
warn "$class->$ret( @_ )\n";
$class->$ret( @_ )
};
};
}
sub foo::bar {
print "got: @_[1 .. $#_]\n";
}
my $m = foo->can("bar");
$m->(qw(ichi ni san shi));
__output__
foo->CODE(0x81080f8)( ichi ni san shi )
got: ichi ni san shi
Or something else perhaps?
HTH
_________ broquaint | [reply] [d/l] |
|
| [reply] |
|
It's far, far too late to make this the default behaviour. This'd be a matter for a new method in UNIVERSAL (which has its own issues) or a middle OO layer.
| [reply] |
Re: Why isn't ->can() curried?
by Anonymous Monk on Jan 20, 2003 at 18:33 UTC
|
When I have wanted to use can for anything other than the truth value I have generally wanted to either verify which function implements it (which your suggestion breaks) or else I have wanted to wrap the existing implementation with another and it is not certain that I want to necessarily use the same object. Indeed I might locate can with the class and then feed it real objects later.
I don't want to do either often, but on the rare occasions when I do, your suggestion is less convenient than the current behaviour.
But more than that, the vast majority of the time when people want to check can they just want to check truth. Why create a closure just to see it get thrown away?
But if you really want it, just create another method to do what you want:
sub UNIVERSAL::bind_meth {
my ($self, $meth, @args) = @_;
my $func = $self->can($meth);
if (defined($func)) {
return sub {$func->($self, @args, @_)};
}
else {
return undef;
}
}
And now you can curry a method, and curry a few arguments as well while you are at currying favour. And I still get the can that I know and like. | [reply] [d/l] |
|
This is what comes of spending time with other languages. *grin* In this case it's E which has a home page at http://www.erights.org. It had never occured to me that people would want to compare the code references from ->can. When is that useful?
Seeking Green geeks in Minnesota
| [reply] |
|
One use is to verify that a subclass has actually implemented an abstract interface.
| [reply] |
|
Re: Why isn't ->can() curried?
by chromatic (Archbishop) on Jan 20, 2003 at 17:33 UTC
|
How do you tell, programatically, whether the function is intended to be called as a method or a function?
| [reply] |
|
| [reply] |
|
Paint me daft, then, I do it all the time in tests. :)
Perhaps any extra arguments to can() could be bound to the subref returned. It's a nice idea; it just seems really hard to get super-scary magic right. Here's some untested code that seems somewhat useful:
use Scalar::Util 'blessed';
sub curried_can
{
my ($thingie, $func) = splice( @_, 0, 2 );
my $sub = UNIVERSAL::can( $thingie, $func );
# $thingie cannot $func
return unless $sub;
# first argument is an object
return sub { $thingie->$func( @_ ) } if blessed $thingie;
# first argument is a class name, no arguments
return $sub unless @_;
# first argument is a class name, curried arguments
return sub { $sub->( @_ ) };
}
| [reply] [d/l] [select] |
Re: Why isn't ->can() curried?
by hardburn (Abbot) on Jan 20, 2003 at 17:04 UTC
|
The current implementation allows you to do totally lame-brained things . . .
Those things things are allowed anyway. Remember: Perl allows you to do anything you want. There is no such thing as truly private data in Perl the same way it is in Java (for example). Perl's way of doing private data is to make it inconvieant to access with a little comment that says "anybody who uses this deserves what they get" :)
| [reply] |
|
But since this isn't about private data... Anyhow I've got no problem with people who can go grab or alter the object in the method. I just think the object should be there. Right now it's not. This is a completely different concern.
Seeking Green geeks in Minnesota
| [reply] |