This code will print out 'Duo' even though $var is not a dynamic variable with a *
twigil:
our $var="Duo";
sub sub1() {
say $*var;
}
sub1();
#output is 'Duo'
Adding a unit package ABC;
at the start gives a compile time error "Dynamic variable $*var not found":
unit package ABC;
our $var="Duo";
sub sub1() {
say $*var;
}
sub1();
# compile time error
Adding a * twigil in this case makes the variable accessible.
Why the difference?
Edit 1:
Using my
instead of our
is a compile time error with or without a package, even though this would mean the same lexical scope in my understanding.
Are variables which are intended to be used dynamically, to be declared explicitly as such (like all the examples I can find). If so how does our
allow the above to work? I'm confused.
Edit 2:
I think the following demonstrates why I'm confused:
our $var="non dynamic"; #1
{say $*var;}
our $*var="dynamic"; #2
{say $*var;}
#With #2 commented output is
#non dynamic
#non dynamic
#
#With #2 in place output becomes
#(Any)
#dynamic
In the first case (#2 commented) I'm accessing a non dynamic variable dynamically (twice).
In the second case the our $var
variable is getting clobbered when the our $*var
is declared and accessing same dynamic variable is resolving to two seperate variables.
Static variables (should) remain the same e.g. temperature of a water bath, k constant of a particular spring. Dynamic variables change as the experiment progresses e.g. air temperature and pressure, amount of natural light.
In C, variables are always statically (or lexically) scoped i.e., binding of a variable can be determined by program text and is independent of the run-time function call stack.
Physical observable intrinsic to a system (so time is not a dynamical variable).
Seems like dynamic variables are looked up in the GLOBAL
name space. Thus the following works:
unit package ABC;
$GLOBAL::var="Duo";
sub sub1() {
say $*var;
}
sub1();
#output is 'Duo'
The reason your first example works is that (according to the documentation):
The user's program starts in the
GLOBAL
package, so "our" declarations in the mainline code go into that package by default.
Dynamic variable lookup conceptually happens in all dynamic scopes. Dynamic scopes are first PROCESS::
, then GLOBAL::
and then whatever dynamic scopes that the program has.
So when you look up a dynamic variable, it will first look in all dynamic scopes from the current down. When it doesn't find it there, it will then look in GLOBAL::
, and if not found, in PROCESS::
.
For example, if you want to print something on STDOUT, it will look up the $*OUT
dynamic variable. If you did not define one somewhere in your dynamic scopes, it will use the one from PROCESS::
:
dd PROCESS::<$OUT>;
# IO::Handle element = IO::Handle.new(path => IO::Special.new("<STDOUT>")...)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With