cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
  • JMP 19 is here! See the new features at jmp.com/new.
  • Register to attend Discovery Summit 2025 Online: Early Users Edition, Sept. 24-25.
Choose Language Hide Translation Bar
noblea30
Level I

How does scope of variables work in JSL

I'm sure this is posted somewhere already, but I wasn't able to find it.

 

I'm confused how the scope of variables is handled in JSL.  Could someone help to clarify how it works.

 

I almost always use i as the indexing variable for loops.  For example, in my script I will have a for loop with i as the index that calls another function.  In this function, there is another for loop with i as the index.  This has never been a problem in C/Java/etc.  It seems that sometimes it works in jsl and other times it doesn't.  I don't have an example because I havn't been able to figure out exactly where the problem occurs.  I think it is a basic understanding of the scope of variables in JSL though.

1 ACCEPTED SOLUTION

Accepted Solutions
txnelson
Super User

Re: How does scope of variables work in JSL

In JSL, a variable, lets use your example of a variable called "i" is described as

     namespace:i

If nothing is specified to set a namespace, the formal specification is:

     ::i

Since the default namespace in JSL is a namespace named ":"......pretty wierd, but there are historical reasons for this.  So if you enter in

     i = 7;

What JMP is seeing is:

     ::i = 7;

So, now if in any part of a JSL script, the variable i is changed, and then referenced later on, it will have the new value

showit = Function( {I},
     Show(I);
);
I = 2;
showit(I);

I=3;
showit(I);

it returns

I = 2;
I = 3;

Now, a function can isolate a variable, by making the variable local to the function

showit = Function( {I},{I},
     I=55;
     Show(I);
);
I = 2;
showit(I);

show(i);

The result of this code is:

I = 55;
i = 2;

notice, that the value of i for the global use of it has not changed.

 

Now for some final confusion:

When I said that the value of i can be changed, and all subsequent uses of i will reflect that change, that means it will be changed even in different scripts that are being run.  So if a new script is run that has the variable i in it, it will have the value of the i that was set in the previous JSL script.  Thus, the statement "Names Default to Here( 1 );" was implemented.  This statement does 2 things.  First, it changes the namespace from ":" to "Here".  Seconly, it isolates all of the variables in the "Here" namespace to only the variables in the script that is being run.  So now, if you have the following script

Names Default to Here( 1 );
i = 7;

this instance of the variable i will only be changed by the usage of i within the script.....no other script will have access to the changing of that variable i.

 

P.S.   The formal description of the variable i is:

     here:i

and any variable in the script that is created in the script, after the "Names Default to Here( 1 );" statement will automatically be placed into the namespace call Here.  

 

Jim

View solution in original post

7 REPLIES 7
txnelson
Super User

Re: How does scope of variables work in JSL

In JSL, a variable, lets use your example of a variable called "i" is described as

     namespace:i

If nothing is specified to set a namespace, the formal specification is:

     ::i

Since the default namespace in JSL is a namespace named ":"......pretty wierd, but there are historical reasons for this.  So if you enter in

     i = 7;

What JMP is seeing is:

     ::i = 7;

So, now if in any part of a JSL script, the variable i is changed, and then referenced later on, it will have the new value

showit = Function( {I},
     Show(I);
);
I = 2;
showit(I);

I=3;
showit(I);

it returns

I = 2;
I = 3;

Now, a function can isolate a variable, by making the variable local to the function

showit = Function( {I},{I},
     I=55;
     Show(I);
);
I = 2;
showit(I);

show(i);

The result of this code is:

I = 55;
i = 2;

notice, that the value of i for the global use of it has not changed.

 

Now for some final confusion:

When I said that the value of i can be changed, and all subsequent uses of i will reflect that change, that means it will be changed even in different scripts that are being run.  So if a new script is run that has the variable i in it, it will have the value of the i that was set in the previous JSL script.  Thus, the statement "Names Default to Here( 1 );" was implemented.  This statement does 2 things.  First, it changes the namespace from ":" to "Here".  Seconly, it isolates all of the variables in the "Here" namespace to only the variables in the script that is being run.  So now, if you have the following script

Names Default to Here( 1 );
i = 7;

this instance of the variable i will only be changed by the usage of i within the script.....no other script will have access to the changing of that variable i.

 

P.S.   The formal description of the variable i is:

     here:i

and any variable in the script that is created in the script, after the "Names Default to Here( 1 );" statement will automatically be placed into the namespace call Here.  

 

Jim
hogi
Level XIII

Re: How does scope of variables work in JSL

Names Default to Here( 1 );
i = 7;
show(here:i)

I cannot use the "here:" to explicitly address variables in there here namespace?

Why are columns addresses via e.g. ":sex".
Empty namespace means: "current data table()" ? 

txnelson
Super User

Re: How does scope of variables work in JSL

Your code works just fine for me.  

//:*/
Names Default to Here( 1 );
i = 7;
show(here:i)
/*:

here:i = 7;

Original JMP notation was a single colon was a data table column reference, and a double colon was a memory variable reference.  If the colon(s) were left off, typically JMP assumed it was a global memory variable.

When Namespaces came around, the notation changed to Namespace : memory variable   and Data Table() : data table column.

Names Default to Here(1); changed the default namespace from the Global Namespace, to a Namespace named Here. Variable referenced without a colon would now use the Namespace "Here"

 

 

Jim
hogi
Level XIII

Re: How does scope of variables work in JSL

Hi @txnelson .
many thanks for the background info about the history of scoping and namespaces.
Knowing where it came from helps a lot to understand why it's like this now .

Thanks for double checking my code.
Hm, let's check the symbols in the memory ...
Ouch! I must have forgotten to run the

Names Default to Here( 1 );

in my code.

KasperSchlosser
Level III

Re: How does scope of variables work in JSL

There is some pages in the jmp help that explains how scope works in jmp, and how names are resolved:
Local Namespaces

Advanced Scoping and Namespaces

Reference Namespaces and Scopes

 

By default most variables will be put in the global scope, shared across the jmp session.

Running the script

a = 1;
show(a); 

 

will show a = 1

running

 

show(a);
a = 3;
show(a);

will show a = 1, then a = 3 as the variable is shared.

 

Scripts can be (somewhat) isolated by putting Names Default to Here(1) in the script.

This creates a scope "here" that is only accessible by the script, and exist for the lifetime of the script

 

Names Default to Here(1);
show(isempty(a));
a = 1;
show(isempty(a));

If the above script will show 1, 0 the first time its run and 0, 0 the second time its run, closing the script window resets the here scope.

 

There is also local (and local here) blocks, where we can specify variables that a only accessible to that part of the code.

 

Names Default to Here(1);
a = 1;
b = 2;
show(a); // 1
local( {a},
	a = 3;
	show(a); // 3
	show(b); // 2
);
show(a); // 1

 

Finally there are namespaces, which creates a "place" where we can put variables.

 

Names Default to Here(1);
ns = New Namespace("test");
a = 1;
ns:a = 3;
show(a, ns:a); // 1, 3

Note that namespaces are globally accessible, so if you have two scripts that both a namespace with the same name, they will access the same variables. This can be mitigated by using anonymous namespaces.

 

What can trick people, and sounds like the problem you're having is that variables in functions default to Global/Here scope.

 

 

Names Default to Here(1);
f1 = Function({},
	a = 1;
);
a = 2;
show(a); // 2
f1();
show(a) // 1

There is the option to either specify which variables should be local to the function, as txnelson explained. there is also the {Default Local Option}

Names Default to Here(1);
f1 = Function({},
	i = i+1;
);
f2 = Function({},{Default Local},
	i = i+1;
);

//shows 2,4
For(i = 1, i <= 5, i++,
	f1();
	show(i)
);

//shows 1,2,3,4,5
For(i = 1, i <= 5, i++,
	f2();
	show(i)
)

It sounds like this is the problem you mentioned.

 

Other peculiarities:

There some peculiarities with functions compared to most other languages. if a variable isn't defined in the local scope JMP will look at the surrounding scope. For functions this is the entire call stack.

Names Default to Here(1);
show_fun = Function({},{Default Local},
	show(a,b);
);

f1 = Function({},{Default Local},
	a = 3;
	show_fun();
);

f2 = Function({},{Default Local},
	b = 4;
	f1();
);

a = 1;
b = 2;

show_fun(); // 1,2
f1(); // 3,2
f2(); // 3,4

 

 

hogi
Level XIII

Re: How does scope of variables work in JSL

hi @KasperSchlosser , very nice overview of Scoping : )

hogi
Level XIII

Re: How does scope of variables work in JSL

An important detail:
The script window is just part of the Here namespace.

Windows and reports created from the 'Here' namespace have access to it as well.


Simply run the code, close the script window, and observe the behavior of x in the Here namespace.

Names Default to Here(1);
x=5;
Caption("x is" || Char(here:x));
x=6;
new window("Here", Button box ("X= ? ", Caption("x = " || Char(here:x));x++));

 

Recommended Articles