Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Default filehandles, or topicalizing filehandles, or something

1 view
Skip to first unread message

Brian D Foy

unread,
May 1, 2007, 11:01:25 AM5/1/07
to perl6-l...@perl.org
I was thinking about default filehandles yesterday. select() doesn't
seem to be around except as an "Unfiled" function in S16.

Then, as I was looking at

.say( "Hello World" );

and

$ERR.say( "Hello standard error" );

I figured this might work, and does. Topicalizing a filehandle kinda
acts almost like a default filehandle:

$_ = $*ERR;
.say( "Hello standard error" );

But, of course, that won't work for say() used as a function:

say "Hello standard error" ;

Then, I thought I might assign to $*OUT, which doesn't work in pugs
(and I might have missed the part of the spec that says these are
read-only):

my $saved_standard = $*OUT;
$*OUT = $*ERR; # this is an error

say "This goes to stderr"; # not until previous line works
say $saved_standard: "This goes to stdout"; # just fine

Is there going to be a Perl 6 feature for this?

Jonathan Lang

unread,
May 1, 2007, 12:26:38 PM5/1/07
to brian d foy, p6l
On 5/1/07, brian d foy <brian...@gmail.com> wrote:
> I was thinking about default filehandles yesterday. select() doesn't
> seem to be around except as an "Unfiled" function in S16.
>
> Then, as I was looking at
>
> .say( "Hello World" );

At various times, I have seen something to the effect of each of the
following being bandied about:

$*OUT.say( "Hello World" );
"Hello World".say;

That is, both filehandles and strings have 'say' methods that do
essentially the same thing, but using subtly different syntax. How
would I use &("Hello World".say) to write to filehandle $FH? My gut
reaction would be to use an adverb for the purpose:

"Hello World".say :to($FH);

This would also work for the sub version:

say :to($FH) "Hello World";

With this in mind, you probably could create a localized alias for
'say', if you wanted to:

{
my &say := &OUTER::say.assuming(:to($FH));
say "Hello World"; # same as 'say "Hello World" :to($FH);'
}

The catch with this is that you'd have to do this for each output
routine separately.

How about this: Do the output routines default to the global
filehandles directly, or do they default to lexical bindings of them?
That is, does 'say' output to $*OUT in the absence of an explicit
filehandle, or does it output to $OUT (with the latter normally being
bound to $*OUT)? If the latter, you should be able to redirect all of
your output in the rest of the current scope by saying:

$OUT := $*ERR;

I can understand not being able to rebind the global filehandles.
After all: once they're rebound, how would you ever find what they
were originally bound to?

--
Jonathan "Dataweaver" Lang

Larry Wall

unread,
May 1, 2007, 1:18:20 PM5/1/07
to p6l
On Tue, May 01, 2007 at 09:26:38AM -0700, Jonathan Lang wrote:
: On 5/1/07, brian d foy <brian...@gmail.com> wrote:
: >I was thinking about default filehandles yesterday. select() doesn't
: >seem to be around except as an "Unfiled" function in S16.
: >
: >Then, as I was looking at
: >
: > .say( "Hello World" );
:
: At various times, I have seen something to the effect of each of the
: following being bandied about:
:
: $*OUT.say( "Hello World" );
: "Hello World".say;
:
: That is, both filehandles and strings have 'say' methods that do
: essentially the same thing, but using subtly different syntax. How
: would I use &("Hello World".say) to write to filehandle $FH? My gut
: reaction would be to use an adverb for the purpose:
:
: "Hello World".say :to($FH);
:
: This would also work for the sub version:
:
: say :to($FH) "Hello World";

Don't need a named arg, since we can simply be polymorphic on strings vs
filehandles, which thankfully do not overlap semantically:

"Hello World".say($FH)
$FH.say("Hello World")

: With this in mind, you probably could create a localized alias for


: 'say', if you wanted to:
:
: {
: my &say := &OUTER::say.assuming(:to($FH));
: say "Hello World"; # same as 'say "Hello World" :to($FH);'
: }
:
: The catch with this is that you'd have to do this for each output
: routine separately.

You don't always want lexical scoping for this sort of thing; you
often want dynamic scoping instead.

: How about this: Do the output routines default to the global


: filehandles directly, or do they default to lexical bindings of them?
: That is, does 'say' output to $*OUT in the absence of an explicit
: filehandle, or does it output to $OUT (with the latter normally being
: bound to $*OUT)? If the latter, you should be able to redirect all of
: your output in the rest of the current scope by saying:
:
: $OUT := $*ERR;
:
: I can understand not being able to rebind the global filehandles.
: After all: once they're rebound, how would you ever find what they
: were originally bound to?

The plan introduced in A06 was to leave $*('IN'|'OUT'|'ERR') bound
to stdin, stdout, and stderr (which can still be dickered with on
the POSIXy level, of course), and instead emulate p5's select(FH)
using a global variable $*DEFOUT for the default handle of print
(and now say as well).

I note that $*DEFOUT didn't make it into any of the synopses (though it
did make it to pugs/t/builtins/io/say_and_print.t, oddly), so I've just
added it to pugs/docs/Spec/IO.pod, the proto-synopsis on IO.

Anyway, you should (eventually) just be able to say

{
temp $*DEFOUT := $MYFH;
foo();
}

to redirect the default output of foo() and then restore at the end of the
dynamic scope. That's an improvement over dancing the select twostep.

Larry

Mark J. Reed

unread,
May 1, 2007, 1:41:45 PM5/1/07
to p6l
On 5/1/07, Larry Wall <la...@wall.org> wrote:
> The plan introduced in A06 was to leave $*('IN'|'OUT'|'ERR') bound
> to stdin, stdout, and stderr (which can still be dickered with on
> the POSIXy level, of course), and instead emulate p5's select(FH)
> using a global variable $*DEFOUT for the default handle of print
> (and now say as well).

What about the default handle for warn/die? $*DEFERR?

I think I prefer a more significant difference between the default
targets and the POSIXy std* values that they are initialized to, like
the Ruby notion of using global variables initialized to named
constants, e.g. $stderr starts out as equal to STDERR but can be
reassigned...

--
Mark J. Reed <mark...@mail.com>

Larry Wall

unread,
May 1, 2007, 2:23:03 PM5/1/07
to p6l
On Tue, May 01, 2007 at 01:41:45PM -0400, Mark J. Reed wrote:
: On 5/1/07, Larry Wall <la...@wall.org> wrote:
: >The plan introduced in A06 was to leave $*('IN'|'OUT'|'ERR') bound
: >to stdin, stdout, and stderr (which can still be dickered with on
: >the POSIXy level, of course), and instead emulate p5's select(FH)
: >using a global variable $*DEFOUT for the default handle of print
: >(and now say as well).
:
: What about the default handle for warn/die? $*DEFERR?

Could certainly work it the same way.

: I think I prefer a more significant difference between the default


: targets and the POSIXy std* values that they are initialized to, like
: the Ruby notion of using global variables initialized to named
: constants, e.g. $stderr starts out as equal to STDERR but can be
: reassigned...

Well, the question is, what does a subprocess get for fd(2) after
you do that? I'd prefer to keep $*ERR nailed to fd(2) in general so
that modifying $*ERR actually changes the stderr of new subprocesses.
But that doesn't give you a method of indirection inside the current
process, so $*DEFERR would be a way to do that. Forcing people
to use an explicit handle in that case would be another approach,
but certainly something like $*DEFERR would be kinder to embedding
systems that want to intercept such messages and log them.

Larry

Mark J. Reed

unread,
May 1, 2007, 5:45:26 PM5/1/07
to p6l
On 5/1/07, Larry Wall <la...@wall.org> wrote:
> : I think I prefer a more significant difference between the default
> : targets and the POSIXy std* values that they are initialized to, like
> : the Ruby notion of using global variables initialized to named
> : constants, e.g. $stderr starts out as equal to STDERR but can be
> : reassigned...
>
> Well, the question is, what does a subprocess get for fd(2) after
> you do that? I'd prefer to keep $*ERR nailed to fd(2) in general so
> that modifying $*ERR actually changes the stderr of new subprocesses.

Ah. I had imagined $*ERR as a bit more ephemeral than that, with an
underlying really-real stderr.

> But that doesn't give you a method of indirection inside the current
> process, so $*DEFERR would be a way to do that. Forcing people
> to use an explicit handle in that case would be another approach,
> but certainly something like $*DEFERR would be kinder to embedding
> systems that want to intercept such messages and log them.

Right. Something akin to P5's $SIG{__WARN__} and $SIG{__DIE__} would
also work, but that never seemed to be quite the right way to do that,
to me.

Larry Wall

unread,
May 1, 2007, 7:08:02 PM5/1/07
to p6l
On Tue, May 01, 2007 at 05:45:26PM -0400, Mark J. Reed wrote:
: Right. Something akin to P5's $SIG{__WARN__} and $SIG{__DIE__} would

: also work, but that never seemed to be quite the right way to do that,
: to me.

Never seemed quite right to me either. Er, except way back when it did... :/

In P6 such hooks are unnecessary for two reasons:

* Exception handlers are executed before the stack is unwound, so
a surrounding dynamic scope can get control at that point.

* Warnings are just exceptions that default to restarting, so the same
considerations apply.

And even if we did decide to install some kind of temporizable
global hook for such callbacks, I wouldn't put it into %SIG
these days. I'm not even sure signals belong in %SIG anymore.
Seems to me they should just be event objects coming in via some
feed to the event-driven underbelly of the program, assuming
we go ahead with a unified events/threads model as suggested by
http://www.seas.upenn.edu/~lipeng/homepage/unify.html.

Larry

0 new messages