On Sat, Nov 23, 2002 at 08:46:03PM -0600, Me wrote:
: First, I'd like to confirm I've understood
: C<temp> and C<let> right:
:
: 1. C<temp> dynamically scopes changes to a
: variable's value to the enclosing block.
: It does not dynamically scope the name.
: The variable can obviously be a global.
: It can also make sense if it is lexical.
: Is the latter currently allowed?
I'm planning to allow it unless someone can come up with a good reason not to.
: 2. C<let> is a conditional C<temp>; it only
: restores a variable's value if, on exit
: from the enclosing block, the block is
: somehow considered to have "failed". It
: can be applied to a global or lexical.
At the moment, it doesn't apply to either. It applies only to the
current regex's variables. It is a bit of an inconsistency that
in the current model, regex variables are lexically scoped but not
actually declared. This may be a mistake.
: The above two features are basically sugar
: for what would otherwise be achieved with
: paired FIRST/LAST/UNDO blocks.
Well, there's no UNDO defined for regex backtracking unless we define
some kind of BACK block, but conceptually you're basically right.
: Both must be applied to an existing variable.
Not strictly true. if you say
/foo bar { let $baz = 2 } /
the $baz is creating a new variable within the scope of the surrounding regex.
: Next, I want to do a better job of stating
: a problem I wonder about:
:
: Consider "environmental" values such as
: "screen sizes, graphics contexts, file
: handles, environment variables, and
: foreign interface environment handles." [1]
:
: Consider a sub One that is going to call
: a 10 deep stack of subs such that sub Ten
: needs to access one of these environmental
: values. How do you pass the data?
:
: A. Globals. Bad. Disastrous in threads.
:
: B. Passed as args to all intervening subs.
: Verbose. Sometimes incredibly verbose.
:
: C. Aggregate info into objects. But then
: you still have to do either 1 or 2 above
: with the object references. And it's a
: shame to be forced to the object paradigm
: unnecessarily.
:
: D. Use $CALLERS::. Relatively succinct, but
: definitely error-prone and ugly.
But you haven't mentioned what's really going on with package
variables:
E. Passed via thread-local storage. Under I-threads, package variables
are *not* shared by default among threads, so they can be scoped
dynamically without the threading problems of A. Package variables
are global only if you squint really hard.
: Given what I understand of Perl 6 syntax,
: Parrot, and Perl philosophy, I suspect P6
: should, and could fairly easily, provide a
: good solution to the problem outlined above.
:
: Does anyone agree the problem I've outlined
: is inadequately addressed by $CALLERS::?
The real question is, do I agree. :-)
: In previous emails I've suggested:
:
: 1. The notion of something like attaching
: a C<passed> property on variables, and
: picking appropriate defaults for its
: args (not/ro/rw), to allow the writer
: of a sub to easily strictly limit what
: a called sub can access.
I think the granularity is wrong on this. Trying to mesh the
namespaces of caller and callee is a big problem as soon as you
have multiple callees with different ideas. In other words, I think
it's probably a mistake to try to generalize implicit $_ passing to
any name.
: 2. The notion of args that are explicitly
: defined in a sub's sig but implicitly
: passed. This kills most of the verbosity
: of B above, while, in combination with
: the previous point, being otherwise just
: as safe as passing args explicitly all
: the way down the call stack.
We already have currying, and I think that notion should be extended to
handle any caller-instituted defaulting. The granularity can be controlled
on a sub-by-sub or on a class-by-class basis.
# curry sub
my $DBhandle = mumble();
my &shortcut ::= &longcut.assuming(handle => $DBhandle);
# curry all methods of a class
use Dog.assuming(tail => "cut_short", ears => "cut_long");
my $little_dog = Dog.where_oh_where();
or some such. If there are early-binding/late-binding issues we
should address those as part of the currying design. For instance,
it's not clear above whether $DBhandle is evaluated at compile time
or run time. I think we have to say that it's a binding, which means
the value of handle depends on the *current* value of $DBhandle each
time the shortcut is called.
Basically, the parameter list of the subroutine is already providing a
limited namespace to be shared by caller and callee. If the caller really
wants to bind to a variable of the same name, they can always say
my $bar;
&foo.assuming(bar => $bar)
But I think it would be wrong for the callee to start forcing its
namespace into the namespace of the caller beyond what we already do
with named parameter syntax (and $_).
Larry