Function like print with optional filehandle?

S

Steve Roscio

Howdy -

How do I write a function that accepts arguments like print(), where a
filehandle is optional. For example, a function myprint() that can be
used like this:

myprint "foo", "bar";
myprint STDERR "foo", "bar";
myprint $fh "foo", "bar";
myprint {$xyz->{fh}} "foo", "bar";

Must I extend IO::Handle to do this, and have two functions?
Thanx!
- Steve
 
S

smallpond

Howdy -

How do I write a function that accepts arguments like print(), where a
filehandle is optional. For example, a function myprint() that can be
used like this:

myprint "foo", "bar";
myprint STDERR "foo", "bar";
myprint $fh "foo", "bar";
myprint {$xyz->{fh}} "foo", "bar";

Must I extend IO::Handle to do this, and have two functions?
Thanx!
- Steve

perldoc -f print
 
H

Hans Mulder

Steve said:
Howdy -

How do I write a function that accepts arguments like print(), where a
filehandle is optional. For example, a function myprint() that can be
used like this:

myprint "foo", "bar";
myprint STDERR "foo", "bar";
myprint $fh "foo", "bar";
myprint {$xyz->{fh}} "foo", "bar";

There is no way to do that. Only built-in functions can have optional
arguments like that.
Must I extend IO::Handle to do this, and have two functions?

You can write two functions; one with a handle argument and one without.

There's no need to extend IO:Handle, normal functions will suffice.

Hope this helps,

-- HansM
 
S

Steve Roscio

perldoc -f print

Thanx smallpond, but perhaps I didn't explain my question properly.
Let me try again, maybe this will be clearer:

What syntax do I use for my own subroutine so that it can take an
optional filehandle as the first space-delimited argument.
I want to write a subroutine that can be called like this:

foo "abc"; # Without filehandle
foo LOG "abc"; # With filehandle, Note: NO COMMA

My request has nothing to do with print(), other than that the print
function also uses this syntax.

I believe this syntax is along the lines of: SUBNAME CLASSNAME ARGS;
and I know this syntax has some special name, but my old brain can't
recall it.

- Steve
 
S

Steve Roscio

There is no way to do that

Thanx Hans M. OK, I'll stick with a more conventional comma syntax:

Use:
foo "abc";
foo *LOG, "abc";

sub foo {
my $fh = defined fileno($_[0]||'')? shift : *STDOUT;
#... rest of args in @_ like normal
}
 
T

Tad J McClellan

Steve Roscio said:
How do I write a function that accepts arguments like print(),


You can't.

You can write one that accepts arguments almost like print though...

where a
filehandle is optional. For example, a function myprint() that can be
used like this:

myprint "foo", "bar";
myprint STDERR "foo", "bar";
^^^^^^

This one cannot be done, but that isn't much of a handicap since
it is a form of only historical interest.

myprint $fh "foo", "bar";
myprint {$xyz->{fh}} "foo", "bar";
^ ^
^ ^ a hash ref?


------------------------
#!/usr/bin/perl
use warnings;
use strict;

sub myprint {
if ( ref $_[0] eq 'GLOB' )
{ print {shift} @_ }
else
{ print @_ }
}

open my $fh, '>', "out.1" or die "could not open $!";

my $xyz;
open $xyz->{fh}, '>', "out.2" or die "could not open $!";

myprint "foo", "bar";
myprint $fh, "foo1", "bar1";
myprint $xyz->{fh}, "foo2", "bar2";
 
T

Tim McDaniel

^ ^
^ ^ a hash ref?

A code ref. "man perlsub" shows how users could declare their own
subs with prototypes that match those of builtin functions. One
example is

sub mygrep (&@) mygrep { /foo/ } $a, $b, $c
 
X

xhoster

A code ref. "man perlsub" shows how users could declare their own
subs with prototypes that match those of builtin functions. One
example is

Since he specified he wants it to behave like print, then he wants it
to be neither a hashref nor a coderef, but rather a code-block, which is
what it would be with print.
sub mygrep (&@) mygrep { /foo/ } $a, $b, $c

But in the absence of a prototype, it seems to be interpreted as a code
block, whose value is interpreted as an OO indirect object notation. He
could use your prototype and then invoke the passed coderef to get the
handle to print to, but then the argument could no longer be optional, and
would have to wrapped in curlies even if it were a simple scalar.

Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
S

Steve Roscio

By the way, I found out how to do this. Look at the Perl6::Say source
module. It's done with indirect object syntax and extending IO::Handle.
FWIW.
- Steve
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top