Re: Name collisions in Monad




We spent a lot of time working on the scoping rules in Monad. Scripts
create a new scope when run, and variables _created_ in that new scope are
tossed when the script exits. If you want to affect the global scope, you
can use $global:variable which is similar to tcl upvar. However, in
general, you shouldn't need to worry about scopes too much, unless you have
specific requirements.

I've been working on the about_scope help topic - feedback on whether this
helps or hinders would be appreciated.

Thanks

jim


TOPIC
Function and variable scoping

SHORT DESCRIPTION
The visibility a function or variable has in the Microsoft Shell
(MSH) environment

LONG DESCRIPTION
MSH controls access to variables and functions by limiting where
they are available. This limitation is called scope, and by enforcing
a few simple scoping rules, Windows Command Shell helps ensure
that you do not inadvertently change a variable or function that
has been created elsewhere.

The basic rule of scope is this: Unless you explicitly request
otherwise, a variable can be read or changed only within the
scope where it was created, and a variable can be read in another
scope only if the other scope was created in the scope where the
variable or function was created. When Windows Command Shell
first starts, its scope is the global scope. Whenever you run a
script, call a function, or start a new instance of Windows Command
Shell, a new scope is created. A child scope (that is, a scope
created within another scope) can read variables created within a
parent scope, but it cannot change the variable in the parent scope
unless it explicitly names the scope.

For example, the $home variable is initially set to
$env:HOMEDRIVE + $env:HOMEPATH
Because this is its initial value (as set in the profile.msh
file) when Windows Command Shell starts, that is its value in the
global scope. You then create and run the following script:

"The initial value of `$home is $home"
$home="c:\"
"The new value of `$home is $home"

When you run the script the following is displayed:

The initial value of $home is C:\Documents and Settings\JoeUser
The new value of $home is c:\

However, after the script exits, if you type $home at the command
line, the following is displayed:

C:\Documents and Settings\JoeUser

That is because when a new value is assigned to the variable $home
in the script, a new variable is created within the scope of the
script, and it is that variable that is changed by the variable
assignment, not the global variable. Any further references to that
variable within the script are references to the variable in the
local, not the parent scope. When the script exits, $home no longer
refers to the variable created by the script, but rather to the
global variable. As noted previously, you can change the value
of a variable in a parent scope by explicitly naming the scope when
you refer to the variable. Windows Command Shell provides four labels
for identifying the scope of a variable: local, global, private and
script.

The local scope is always the current scope. A new local scope is
created whenever you run a function or script or start a new instance
of Windows Command Shell. Variables defined within the local scope can
be read or changed within that scope and can be read, but not changed,
by child scopes. Parent scopes can neither read nor change variables
defined in their child scopes.

The global scope is the scope that is created when Windows Command
Shell starts. Variables in the global scope can be changed in child
scopes only if the variable name is explicitly labeled as global, but
global variables can be read by any child scope, even if the global
label is not used, unless the variable name is reused in the child
scope (as in the example earlier in this topic).

The script scope is the scope created when a script executes and
ceases to exist when the script exits. You can use the script label
inside functions in a script, for example, to access variables created
in the script but outside the function.

To refer to a variable in another scope (or to ensure that a variable
reference is to the proper scope), place the scope label before the
variable name, separating them by a colon (:).
The following script shows how variables can be read by child scopes,
redefined within those scopes, and changed in child scopes only by
using a scope label:

$var = "init"
function changevar {
'$var is initially set to "'+$var+'" in the function'
$var = "function"
'$var is now set to "'+$var+'" in the function'
$script:var = "script"
'$var is still set to "'+$var+'" in the function'
'but now $var is set to "'+$script:var+'" in the script scope'
}
changevar
'$var in the script is now set to "'+$var+'"'

Running this script produces the following results:

$var is initially set to "init" in the function
$var is now set to "function" in the function
$var is still set to "function" in the function
but now $var is set to "script" in the script scope
$var in the script is now set to "script"

When the script first calls the function named changevar, $var is
set to the value that was set in the script before the function
definition. When the function assigns a new value to $var, a new
variable is created in the function's scope. The function can change
the value of $var without affecting the variable $var that was
created in the script's scope only by explicitly naming the script
scope when referring to $var. If you use a script to assign a
value to a global variable or to make a function globally available,
you just use the global label, as in the following examples:

$global:home = "c:\user\home"
function global:prompt {(get-location).path + '>'}
The private label indicates that the variable is not available outside
of the current local scope. This is useful when you want to avoid
influencing scopes that are created in child scopes as the following
script shows:

$variable = 3
function a
{
$variable
$private:variable = "one"
$variable
b
}
function b
{
$variable
}
$variable
a
$variable

When run, the output of this script is:
3
3
one
3
3

The use in function 'a' of the private designation means that
$variable is set to "one" only in function 'a'. Without the
private label, the output would be:
3
3
one
one
3

Function 'b' now has a new value for $variable, set by function 'a'.

Like variables, function and filter definitions are also contained
within scope boundaries. This ensures that a script that defines a
function or filter will not replace a function with the same name in
a parent scope unless the global keyword is explicitly used. You can
also use the local, script, and private labels to control the scope
of functions and filters. For more information about creating
functions, type get-help about_Function.

Instead of using the global label in a script to assign variable
values or define functions or filters in the global scope, you can
run a script as a so-called "dot source" script. That is, if you
place a period and a space before the script name when you run it,
Windows Command Shell treats the lines of the script as though you
had typed them at the command prompt. Consequently, the changes you
make in the script take effect in the global, not the script, scope.




--
James W. Truher [MSFT]
Monad Program Management
Microsoft Corporation
This posting is provided "AS IS" with no warranties, and confers no rights.

"Ernst Gunnar Gran" <ernstgr@xxxxxxxxxxxxxxx> wrote in message
news:dmkoub$hlj$1@xxxxxxxxxxxxxxxx
> Hi
>
> I just picked up Monad at ITForum 2004 in Barcelona and had a question for
> Jeffrey Snover that he asked me to post
> onto this newsgrp.
>
> The question is about how Monad handles name collisions. Say I over time
> make up my little library of Monad scripts. I
> can't see a way in Monad to make sure that one global variable, $x, in one
> file does not interfere with another global
> variable, $x, in another file? If I source these two files into a third
> script to use them as tools (which making a
> library is all about) they'll be part of the same scope, right? And then
> the two "library scripts" will operate on the
> same $x which is probably not what I want :) In Perl you solve this
> problem by using the keyword "my", something like
> this;
>
> --lib1--
>
> my $x;
> blablabla...
>
>
> --lib2--
>
> my $x;
> blablabla...
>
>
> and then even if u use lib1 and lib2 "inside the same scope" the first $x
> is local to the first file, and the second
> $x is local to the second file. Shouldn't Monad support something like
> this as well? :)
> (More info about "my": http://perldoc.perl.org/functions/my.html)
>
>
>
> Best Regards,
> Ernst Gunnar Gran
>


.



Relevant Pages

  • Re: Can com+ Hotfix Rollup Package 27 fix my memory problem with WSH. CreateObject/CreateScript?
    ... > these activities have effects that are felt outside of the scope of a script ... Of course in script, the object will be ... > Even the above definition makes no distinction between object variables ... a connection every time I read or write a key, ...
    (microsoft.public.scripting.wsh)
  • Re: One other related Q Re: basic Q: Only one way to make vars live outside of the scope of a functi
    ... >>> directly to the calling script, without having to use global variables ... to get multiple return items from a subprocedure. ... >>> better not to mix scope and use global variables for multiple return ... before terminating the object reference. ...
    (microsoft.public.scripting.vbscript)
  • Re: new to scripting.. the below script stops after first run..
    ... I have exports from my unix servers that aren't compatible with MS for a straight import so I've fiddled with the data, and now I want to just run the same script many times and pass it a bunch of parameters.. ... Echo Changing scope options ... Netsh dhcp server %server% scope %netid% add iprange %iprangestart% %iprangeend% BOTH> NUL ...
    (microsoft.public.windows.server.scripting)
  • Re: [MSH] WMI Help
    ... access the variable in the global scope whether or not the script is ... dot-sourced into the global scope then $script:class is equivalent to ... >> defined so it will search the stack and find it in the parent scope and ...
    (microsoft.public.windows.server.scripting)
  • Re: Dynamic variable names
    ... Note that var defines the scope of a variable. ... variable you initialize belongs to the scope where it has been ... But it has been added no assignment yet, ...
    (comp.lang.javascript)

Loading