I am trying to apply a prototype to a copy of a subroutine without modifying the existing subroutine. That is, this is not normal:
use Scalar::Util 'set_prototype';
sub foo {};
*bar = \&foo;
set_prototype(\&bar, '$');
What I want to achieve can be done with goto &sub:
sub foo {};
sub bar($) {
goto &foo;
}
However, this introduces unnecessary overhead for which I am not interested. So my question is: Is there a way to make a (shallow) copy of a subroutine (CV) so that installing a copy prototype does not affect the original? Ie something like
use Scalar::Util 'set_prototype';
sub foo {};
*bar = magical_cv_copy(\&foo);
set_prototype(\&bar, '$');
I looked Sub:Clone, but it seems to be outdated and will not install it on my system without forcing it. I would rather not write XS code for this.
Test version to clarify my requirements:
use strict;
use warnings;
use Test::More tests => 7;
use Scalar::Util qw/refaddr set_prototype/;
sub foo {
my ($x) = @_;
return 40 + $x;
}
*bar = then_a_miracle_occurs(\&foo);
ok not(defined prototype \&foo), 'foo has no prototype';
ok not(defined prototype \&bar), 'bar has no prototype';
isnt refaddr(\&foo), refaddr(\&bar), 'foo and bar are distinct';
set_prototype \&bar, '$';
ok not(defined prototype \&foo), 'foo still has no prototype';
is prototype(\&bar), '$', 'bar has the correct prototype';
is foo(2), 42, 'foo has correct behavior';
is bar(2), 42, 'bar has correct behavior';
sub then_a_miracle_occurs {
my ($cv) = @_;
}
To avoid the XY problem:
X- , foo . , , , . foo - XS.
foo, , foo.
, Y-: .