I have a subroutine,
use experimental "signatures";
sub foo {
my $fh = +shift;
open ($fh, '>', 'default_file') unless defined $fh;
}
I would like to port that to subroutine signatures. Is it possible to set $fh to default to a filehandle that points to default_file
.
Something like this
sub foo ($fh=open($fh,">",foo")) {}
or even with a do{}
block,
sub foo ($fh=do { open($fh,">",foo"), $fh } ) {}
I know I can get this syntax if I use or create a wrapper. But it just seems like there should be a way of some sort to get this done without invoking IO::File and the like.
Can also cheat, just a little, and use a name-less and value-less optional argument
use experimental "signatures";
sub foo ($=) {
my $fh = shift;
open $fh, '>', "foo.txt" or die $! if not defined $fh;
say $fh 42;
return $fh;
}
This fakes it in the sense that it processes arguments "normally" (as it would without signatures). However, one of nice things with signatures is that the @_
is kept pristine and can also be used
When using a signature, the arguments are still available in the special array variable
@_
, in addition to the lexical variables of the signature.
I don't see a good reason to not use that. † Even as it pushes the argument processing back into the sub's body, you still get other benefits of signatures -- and an added measure of flexibility.
† The stylistic point of handling arguments in the signature, including their defaults, is denied here anyway, merely by how much there is to do for this default.
Pending a better answer, I think the only method is to use a wrapper,
use IO::File;
sub foo ( $fh=IO::File->new("default_file", "w") ) {
print $fh 42
}
The second attempt you showed is almost valid, you just need another variable to stand in since $fh
doesn't exist yet when assigning the default; and to return it in a separate statement from where it's declared. You could abuse global variables to do this of course but that's ugly and leaky.
sub foo ($fh=do { open(my $d,">","foo"); $d } ) {}
This of course should have error handling.
sub foo ($fh=do { open(my $d,">","foo") or die "Failed to open 'foo': $!"; $d } ) {}
A proposed extension to signatures could be used to do it slightly differently, but I'm not sure if this is any better:
sub foo (?$d, $fh=(open($d,">","foo") || die "Failed to open 'foo': $!", $d) ) {}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.