How to declare the function prototype if I want to get similar parameter passing as built-in print
, like accepts optional first parameter which is file handle? For example, the calling syntax would be myprint $filehandle @mylist
.

- 254,901
- 44
- 429
- 631

- 20,586
- 28
- 90
- 134
-
You don't need a prototype. You should never use prototypes unless you're certain what you're doing and have a great reason.Just pass the lexical file handle as a parameter. Don't use global file handles. If you need to use a built-in file handle like `STDOUT` then pass a reference to the glob: `\*STDOUT`. – Borodin Jan 10 '18 at 20:05
-
@Borodin Well, I think the question is about the special syntax of `print`: the filehandle is optional and is _not_ followed by a comma `, `. [This](https://stackoverflow.com/a/388211/5830574) is an interesting answer about redefining `print`. They say it doesn't work. – PerlDuck Jan 10 '18 at 20:12
-
1@Perl: `print $fh` uses `$fh` as an object with a `print` method. It's only valid Perl because it's an established idiom, and it really should be `$fh->print(...)`. If the OP wants that then they should subclass `IO::File`, but it would have to be a very special requirement to need such chicanery. – Borodin Jan 10 '18 at 20:30
-
1@Thomson: Why do you want to do this? What do you need that ordinary subroutines can't offer? It's very odd to want to write something that pretends to be part of the language when it's clearly not. – Borodin Jan 10 '18 at 22:48
-
@Borodin, I am trying to write a logging method and want to get similar syntax as built-in `print`, like if `$filehandle` is not specified, just log to console. I thought `print` is just an built-in Perl function and I could mimic it in my code. – Thomson Jan 10 '18 at 23:50
-
@Thomson: `print` is a built-in operator, but why do you want to emulate it? What's wrong with `sub myprint { ... }`? I assume you wouldn't want to write a replacement for `use`, `for`, `next` etc.? – Borodin Jan 10 '18 at 23:53
-
Just for similarity. I assumed it is in special prototype but I am wrong. Switching to normal Perl function is fine. – Thomson Jan 10 '18 at 23:58
-
1@Thomson: The last thing you want is apparent *similarity* when what you're writing is actually completely different from the core operator. – Borodin Jan 11 '18 at 00:15
2 Answers
The syntax of print
can't be replicated by Perl subs.
$ perl -le'print defined(prototype("CORE::print")) ? "Can" : "Can'\''t", " be replicated"'
Can't be replicated
Specifically, the syntax NAME EXPR LIST
can't be used to call a Perl sub because the syntax is for an indirect method call. NAME EXPR LIST
already means EXPR->NAME(LIST)
Option 1
# myprint $fh, LIST
# myprint *FH, LIST
# myprint \*FH, LIST
sub myprint {
my $fh = shift;
...
}
Option 2
# myprint $fh, LIST
# myprint *FH, LIST
# myprint \*FH, LIST
# myprint FH, LIST
sub myprint(*@) {
my $fh = shift;
if (!ref($fh)) {
$fh = caller().'::'.$fh if $fh !~ /^(?:ARGV|STD(?:IN|OUT|ERR))\z/;
no strict qw( refs );
$fh = \*$fh;
}
...
}
On the flip side, even print
doesn't actually support print EXPR LIST
. It supports the following syntaxes:
print LIST # Short for: print { select() } LIST
print IDENT LIST # Short for: print { \*IDENT } LIST
print $VAR LIST # Short for: print { $VAR } LIST
print BLOCK LIST
You can actually support the final form of print
(for which the others are merely shortcuts):
# myprint { select } LIST
# myprint { $fh } LIST
# myprint { *FH } LIST
# myprint { \*FH } LIST
sub myprint(&@) {
my $fh = shift->();
...
}
I like this solution less than the first two.

- 367,544
- 15
- 269
- 518
-
Any reference about `NAME EXPR LIST` syntax? Haven't got meaning answer via literal search. – Thomson Jan 11 '18 at 06:42
-
You mean indirect method call syntax? A [search](https://www.google.ca/search?q=site%3Aperldoc.perl.org+indirect+method+call+syntax) leads to [this](https://perldoc.perl.org/perlobj.html#Indirect-Object-Syntax) – ikegami Jan 11 '18 at 07:00
print $fh @list
as an example of an indirect method call, equivalent to
$fh->print(@list)
To use a different function that can be indirectly invoked with a filehandle, define it in the IO::Handle
package.
sub IO::Handle::myprint {
my ($self, @list) = @_;
#$self->print(scalar localtime,": ",@list);
print $self scalar localtime, ": ", @list;
}
open my $fh, '>', 'foo';
print $fh "hello\n"; # IO::Handle::print($fh, "hello\n")
myprint $fh "world\n"; # IO::Handle::myprint($fh, "world\n")
close $fh;
This works with Perl v5.16 and better, and doesn't work with Perl v5.12 and earlier, for reasons I haven't investigated (maybe it's because it's not until v5.14 or v5.16 that all filehandles are automatically blessed into IO::File
)
This seems to work on all versions of Perl back to at least v5.8. It's the syntax $self->print(...)
inside the myprint
method that requires v5.16 (or maybe v5.14, whenever it was that all filehandles were automatically blessed into IO::File
) -- print $self ...
still works with older Perls.

- 117,087
- 18
- 149
- 283
-
`print $fh @list` isn't a method call (indirect or otherwise), and it's not equivalent to `$fh->print(@list)` or `IO::Handle::print($fh, "hello\n")`. – ikegami Jan 11 '18 at 01:16
-
`$fh->print(@list)` has worked since 5.8, but you had to make sure IO::Handle was loaded until 5.14. – ikegami Jan 11 '18 at 01:24
-
1Finally, and most importantly, you're are advocating monkey-patching a basic class for no reason. That's horrible advice! – ikegami Jan 11 '18 at 01:31
-
-
Elaborate. Even if the OP had asked to create a method for all file handles (which they didn't), that wouldn't be a reason for doing it. (It would be a reason to tell them not to do it.) What possible reason is there to add `myprint` to IO::Handle? – ikegami Jan 11 '18 at 14:47
-
To create new functions that can be invoked with `func FILEHANDLE LIST` syntax. – mob Jan 11 '18 at 15:00
-
But that's not what you did; you did far far more than that. /// I also see your answer still claims that `print $fh` is equivalent to `$fh->print`. Unlike the latter, the former doesn't call `IO::Handle::print` (unlike what your comment claims). – ikegami Jan 11 '18 at 15:06