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

$/ and $! should be env (and explanation of env variables)

0 views
Skip to first unread message

Luke Palmer

unread,
Jan 1, 2006, 1:34:25 PM1/1/06
to perl6language
I propose that we change $! (formerly global) and $/ (formerly
implicitly lexical) to being env variables. Here is the IRC
conversation where Audrey convinced me:
http://colabti.de/irclogger/irclogger_log/perl6?date=2006-01-01,Sun&sel=1213#l1893

Let me explain env variables, because my misunderstanding of those is
what caused me to oppose the idea. An env variable can be thought of
as an implicit parameter to a function. A function retrieves said
implicit parameters using the + twigil. So this code:

sub bar() {
say $+foo;
}
sub baz() {
env $foo = 42;
bar();
}

Could be rewritten:

sub bar($foo) {
say $foo;
}
sub baz() {
bar(foo => 42);
}

The + twigil is *necessary*, so it's different from a temporized
global. This code:

sub bar() {
say $foo;
}
sub baz() {
env $foo = 42;
bar();
}

Dies with "$foo undeclared at line 2".

Env variables are implicitly passed up through any number of call
frames. So baz() could declare an env $foo, and bar() could call
bar(), which calls quux(), which calls foo(), and foo() could ask for
$+foo.

The decision to make $! non-global is obvious:

sub trace($msg) {
try { say $msg }
}
try {
maybe_dies();
CATCH {
trace("got here");
when X::Foo {...} # uh oh, is referring to trace()'s $!
}
}

Making $! lexical or environmental solves that problem. Keeping it
environmental allows you to write your own catch() handlers.

$/ was formerly lexical, and making it environmental, first of all,
allows substitutions to be regular functions:

$foo.subst(rx| /(.*?)/ |, { "<it>$1</it>" })

Since .subst could choose bind $/ on behalf of its caller.

It is also aesthetically appealing to have all (three) punctuation
variables being environmental.

Here's a patch to S02:

Luke

Index: S02.pod
===================================================================
--- S02.pod (revision 7048)
+++ S02.pod (working copy)
@@ -467,9 +467,7 @@
Many of the special variables of Perl 5 are going away. Those that
apply to some object such as a filehandle will instead be attributes
of the appropriate object. Those that are truly global will have
-global alphabetic names, such as C<$*PID> or C<@*ARGS>. Certain of
-these global values may retain punctuational shortcuts, such as C<$!>
-for C<$*ERROR>.
+global alphabetic names, such as C<$*PID> or C<@*ARGS>.

=item *

@@ -604,9 +602,10 @@
The C<CALLER> package refers to the lexical scope of the (dynamically
scoped) caller. The caller's lexical scope is allowed to hide any
variable except C<$_> from you. In fact, that's the default, and a
-lexical variable must be declared using "C<env>" rather than C<my> to
be visible via C<CALLER>.
-(C<$_> is always environmental. [Conjectural: so are C<$!> and C<$/>.])
-If the variable is not visible in the caller, it returns failure.
+lexical variable must be declared using "C<env>" rather than C<my> to be
+visible via C<CALLER>. (C<$_>, C<$!> and C<$/> are always
+environmental.) If the variable is not visible in the caller, it returns
+failure.

An explicit C<env> declaration is implicitly readonly. You may add
C<is rw> to allow subroutines from modifying your value. C<$_> is

TSa

unread,
Jan 2, 2006, 11:26:43 AM1/2/06
to perl6language
HaloO,

happy new year to Everybody!

Luke Palmer wrote:
> Env variables are implicitly passed up through any number of call
> frames.

Interesting to note that you imagine the call chain to grow upwards
where I would say 'implicitly passed down'. Nevertheless I would
also think of upwards beeing the positive direction where you find
your CALLER's environment with a $+ twigil var or where the $^ twigiled
vars come from ;)

Since exception handling is about *not* returning but calling your
CALLER's CATCH blocks in the same direction as the environments are
traversed there should be some way of navigating in the opposite
direction of these environments up---or down---to the point where
the error occured. Could this be through $- twigil vars? Or by
having an @ENV array that is indexed in opposite call direction yielding
this frame's %ENV? Thus @ENV[-1] would nicely refer to the actual
error environment. And +@ENV tells you how far away you are catching
the error. But this would not allow to retrieve non-exceptional
environmental data frames unless forward indexing from @ENV[+@ENV] and
beyond is supported.

Well, alternative we could have an ERR namespace. BTW, how is the
object data environment handled? Is there a SELF namespace? How much
of that is automagically accessible in CATCH blocks?


> $/ was formerly lexical, and making it environmental, first of all,
> allows substitutions to be regular functions:
>
> $foo.subst(rx| /(.*?)/ |, { "<it>$1</it>" })
>
> Since .subst could choose bind $/ on behalf of its caller.

Just let me get that right. Whatever $foo contains is stringyfied
and passed as $?SELF to .subst with $_ as a readonly alias?
Then the string is copied into an 'env $/ is rw' inside subst and
handed over to some engine level implementation routine which actually
performs the subtitution. Finally .subst returns the value of this $/.
Well, and for an in-place modification of $foo the call reads
$foo.=subst(...), I guess?

Or was the idea to have three declarations

env $_ is rw = CALLER<$_>; # = $?SELF in methods?
env $/ is rw = CALLER<$/>; # = $?SELF in rules?
env $! is rw = undef; # = CALLER<$!> when exceptional

beeing implicitly in effect at the start of every sub (or block)?
Thus subst could just modify $+/ without disturbing CALLER<$foo>
which might actually be invisible to subst?


> It is also aesthetically appealing to have all (three) punctuation
> variables being environmental.

And it clears up the strange notion of lexical my-vars :)
I hope lexical now *only* means scanning braces outwards on
the source code level with capturing of state in the (run)time
dimension thrown in for closure creation, lazy evaluation etc.

Talking about lazy evaluation: does it make sense to unify
the global $*IN and $*OUT with lazy evaluation in general?
That is $OUT is where yield writes it value(s) to and $IN
is for retrieving the input. Iteration constructs automatically
stall or resume coroutines as needed.
--

0 new messages