<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Need help understanding how variables are scoped in expressions in Discussions</title>
    <link>https://community.jmp.com/t5/Discussions/Need-help-understanding-how-variables-are-scoped-in-expressions/m-p/491731#M73314</link>
    <description>&lt;P&gt;Jordan, thanks a lot, it does explain the behavior. I do like your proposed way with namespaces, since the real script has many tables that would share variables in their OnClose statements.&amp;nbsp;&lt;/P&gt;&lt;P&gt;Can you help me understand the following piece of code:&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;		Local( {self = Namespace( Expr( self &amp;lt;&amp;lt; Get Name ) )},
			self:exprA;
			Delete Namespaces( Force( 1 ), self )
		)&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;Local resolves names to local variables, what does that mean? Why do you need to define some variables in curly brackets, what's the purpose? (both Scripting index and documentation don't say much about it).&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Tue, 24 May 2022 17:27:12 GMT</pubDate>
    <dc:creator>miguello</dc:creator>
    <dc:date>2022-05-24T17:27:12Z</dc:date>
    <item>
      <title>Need help understanding how variables are scoped in expressions</title>
      <link>https://community.jmp.com/t5/Discussions/Need-help-understanding-how-variables-are-scoped-in-expressions/m-p/490925#M73290</link>
      <description>&lt;P&gt;Hello all,&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I have a simple example script. Can somebody explain me what are the scopes for the variables here and why it works one way and not another?&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Here's the initial script:&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;Names default to here(1);
Clear Globals();
x="Variable";

exprA = Expr(Write("Here is variable: "||x));
exprB = Expr(
dt1 = Open( "$SAMPLE_DATA/Big Class.jmp" );dt1 &amp;lt;&amp;lt; OnClose(exprA));

exprB;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;The idea is that I open table and give it an expression it needs to run when it's closed. Expression evaluates and changes (not in this example) some variables from the script.&lt;/P&gt;&lt;P&gt;The way it is written it doesn't work - nothing happens, but in my real script it just says it can't find a reference.&lt;/P&gt;&lt;P&gt;Okay, let's try to make ExprA global:&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;Names default to here(1);
Clear Globals();
x="Variable";

::exprA = Expr(Write("Here is variable: "||x));
exprB = Expr(
dt1 = Open( "$SAMPLE_DATA/Big Class.jmp" );dt1 &amp;lt;&amp;lt; OnClose(exprA));

exprB;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;Now it does see the expression, but it still doesn't work, because now it doesn't see the x variable.&lt;/P&gt;&lt;P&gt;Ok, let's make x global too:&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;Names default to here(1);
Clear Globals();
::x="Variable";

::exprA = Expr(Write("Here is variable: "||x));
exprB = Expr(
dt1 = Open( "$SAMPLE_DATA/Big Class.jmp" );dt1 &amp;lt;&amp;lt; OnClose(exprA));

exprB;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;Now it works:&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;Scriptable[]Here is variable: Variable

// Close Data Table: Big Class
Close( "Big Class" );&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;The question: why does it work this way and doesn't work the initial way? I looked to me it should've worked.&lt;/P&gt;&lt;P&gt;I don't like using global variables in this script - any other way to make it work?&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 09 Jun 2023 16:59:54 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/Need-help-understanding-how-variables-are-scoped-in-expressions/m-p/490925#M73290</guid>
      <dc:creator>miguello</dc:creator>
      <dc:date>2023-06-09T16:59:54Z</dc:date>
    </item>
    <item>
      <title>Re: Need help understanding how variables are scoped in expressions</title>
      <link>https://community.jmp.com/t5/Discussions/Need-help-understanding-how-variables-are-scoped-in-expressions/m-p/491125#M73297</link>
      <description>&lt;P&gt;Scoping goes like this&amp;nbsp; -- lookup in &lt;CODE class=" language-jsl"&gt;Local()&lt;/CODE&gt; namespace if it exists, if not lookup in &lt;CODE class=" language-jsl"&gt;Here()&lt;/CODE&gt; namespace if it exists, if not lookup in &lt;CODE class=" language-jsl"&gt;Global()&lt;/CODE&gt; namespace.&amp;nbsp; (Also, it will check the column names of the current data table sometimes as well).&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;What you're doing in your first script is to put the name &lt;CODE class=" language-jsl"&gt;"x"n&lt;/CODE&gt; into the &lt;CODE class=" language-jsl"&gt;Here()&lt;/CODE&gt; namespace with value &lt;CODE class=" language-jsl"&gt;"Variable"&lt;/CODE&gt;, then put the name &lt;CODE class=" language-jsl"&gt;"exprA"n&lt;/CODE&gt; into the &lt;CODE class=" language-jsl"&gt;Here()&lt;/CODE&gt; namespace with value &lt;CODE class=" language-jsl"&gt;Write( "Here is variable: " || x )&lt;/CODE&gt;, then put name &lt;CODE class=" language-jsl"&gt;"exprB"n&lt;/CODE&gt; into the &lt;CODE class=" language-jsl"&gt;Here()&lt;/CODE&gt; namespace with value &lt;CODE class=" language-jsl"&gt;Glue( dt1 = Open( "$SAMPLE_DATA/Big Class.jmp" ), dt1 &amp;lt;&amp;lt; On Close( exprA ) )&lt;/CODE&gt;.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Finally you evaluate &lt;CODE class=" language-jsl"&gt;"exprB"n&lt;/CODE&gt; -- JMP then tries to resolve this name by first checking the &lt;CODE class=" language-jsl"&gt;Local()&lt;/CODE&gt; namespace (it doesn't exist), then the &lt;CODE class=" language-jsl"&gt;Here()&lt;/CODE&gt; namespace and it finds it -- so it runs the expression stored in &lt;CODE class=" language-jsl"&gt;As Scoped( "here", "exprB" )&lt;/CODE&gt;.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;This then loads the table and puts &lt;CODE class=" language-jsl"&gt;exprA&lt;/CODE&gt; as the closing script to the window.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Since this is the end of the script then the &lt;CODE class=" language-jsl"&gt;Here()&lt;/CODE&gt; namespace created for the script is deleted and the memory cleared.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;When you close the table, it finds the literal &lt;CODE class=" language-jsl"&gt;exprA&lt;/CODE&gt; as the closing script, then it tries to scope the name as above (in &lt;CODE class=" language-jsl"&gt;Local()&lt;/CODE&gt;,&amp;nbsp;&lt;CODE class=" language-jsl"&gt;Here()&lt;/CODE&gt;,&amp;nbsp;&lt;CODE class=" language-jsl"&gt;Global()&lt;/CODE&gt;), only this time there is no &lt;CODE class=" language-jsl"&gt;Here()&lt;/CODE&gt; namespace and it cannot find the name in any of the three namespaces, thus throwing an error.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;In general, when you want to add a variable as a static value to an expression that will run in a different scope, use either &lt;CODE class=" language-jsl"&gt;Eval( Eval Expr( ...; Expr( Name Expr( val ) ); ... ) )&lt;/CODE&gt; or some other equivalent.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;In my personal experience I create explicit namespaces for each script (anonymous) then manually scope all variables to the respective namespace.&amp;nbsp; I can then pass this namespace around as needed (and of course I clear and close the namespace when the script is done / window is closed).&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Some examples of how your script could be made to work are as follows:&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;Names Default To Here( 1 );
x = "Variable";

Eval( Eval Expr(
	dt1 = Open( "$SAMPLE_DATA/Big Class.jmp" );
	dt1 &amp;lt;&amp;lt; OnClose( Write( "\!NHere is variable: " || Expr( x ) ) );
) );&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;or&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;Names Default To Here( 1 );
x = "Variable";

exprA = Expr(
	Write( "\!NHere is variable: " || x )
);
Eval( Eval Expr(
	dt1 = Open( "$SAMPLE_DATA/Big Class.jmp" );
	dt1 &amp;lt;&amp;lt; OnClose( x = "rather"; Expr( Name Expr( exprA ) ) );
) );&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;or&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;Names Default To Here( 1 );
self = New Namespace();
self:x = "Variable";

self:exprA = Expr(
	Write( "\!NHere is variable: " || self:x )
);
Eval( Eval Expr(
	dt1 = Open( "$SAMPLE_DATA/Big Class.jmp" );
	dt1 &amp;lt;&amp;lt; OnClose(
		Local( {self = Namespace( Expr( self &amp;lt;&amp;lt; Get Name ) )},
			self:exprA;
			Delete Namespaces( Force( 1 ), self )
		)
	);
) );&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;Note that while many programming languages create local namespaces and keep them around using reference counters until they're no longer needed (such as Python with functions and such), JSL doesn't really do that and it is up to the coder to maintain any persistence and scoping needed. The code inside the &lt;CODE class=" language-jsl"&gt;&amp;lt;&amp;lt;On Close( ... )&lt;/CODE&gt; message is evaluated in a completely separate context to the script that created it with no management of names or scopes.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Hope this helps, it can be a bit confusing!!&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 24 May 2022 07:22:24 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/Need-help-understanding-how-variables-are-scoped-in-expressions/m-p/491125#M73297</guid>
      <dc:creator>ErraticAttack</dc:creator>
      <dc:date>2022-05-24T07:22:24Z</dc:date>
    </item>
    <item>
      <title>Re: Need help understanding how variables are scoped in expressions</title>
      <link>https://community.jmp.com/t5/Discussions/Need-help-understanding-how-variables-are-scoped-in-expressions/m-p/491731#M73314</link>
      <description>&lt;P&gt;Jordan, thanks a lot, it does explain the behavior. I do like your proposed way with namespaces, since the real script has many tables that would share variables in their OnClose statements.&amp;nbsp;&lt;/P&gt;&lt;P&gt;Can you help me understand the following piece of code:&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;		Local( {self = Namespace( Expr( self &amp;lt;&amp;lt; Get Name ) )},
			self:exprA;
			Delete Namespaces( Force( 1 ), self )
		)&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;Local resolves names to local variables, what does that mean? Why do you need to define some variables in curly brackets, what's the purpose? (both Scripting index and documentation don't say much about it).&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 24 May 2022 17:27:12 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/Need-help-understanding-how-variables-are-scoped-in-expressions/m-p/491731#M73314</guid>
      <dc:creator>miguello</dc:creator>
      <dc:date>2022-05-24T17:27:12Z</dc:date>
    </item>
    <item>
      <title>Re: Need help understanding how variables are scoped in expressions</title>
      <link>https://community.jmp.com/t5/Discussions/Need-help-understanding-how-variables-are-scoped-in-expressions/m-p/492019#M73325</link>
      <description>&lt;P&gt;Short answer -- it keeps names from overwriting anything outside the &lt;CODE class=" language-jsl"&gt;Local()&lt;/CODE&gt; block.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Long answer:&lt;/P&gt;&lt;P&gt;For my functions I write them like this:&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;some function = Function( {arg1, arg2, etc},
	{Default Local},
	
	self:arg1 = arg1;
	self:arg2 = arg2;
	
	//do something amazing!
	//call a method:
	self:call method
);
call method = Function( {},
	//do something else amazing!
	1
)&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I then use meta-programming to define &lt;CODE class=" language-jsl"&gt;self&lt;/CODE&gt; and inject a reference into each function, which transforms it to something like:&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;self:some function = Function( {arg1, arg2, etc},
	{Default Local},
	self = Namespace( "#48" );
	
	self:arg1 = arg1;
	self:arg2 = arg2;
	
	//do something amazing!
	//call a method:
	self:call method
);
self:call method = Function( {},
	{self},
	self = Namespace( "#48" );
	//do something else amazing!
	1
)&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;This creates something that is very similar to Python classes (my code is very much different from the above statements, but conceptually similar).&amp;nbsp; The thing that I want to never happen is to have the reference &lt;CODE class=" language-jsl"&gt;self&lt;/CODE&gt; be overwritten by any other value.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Imagine that in a function I have a &lt;CODE class=" language-jsl"&gt;Wait( 1 )&lt;/CODE&gt; function for some reason, and during that wait phase someone closes a table that has a script attached that redefines &lt;CODE class=" language-jsl"&gt;self&lt;/CODE&gt; -- when the wait statement is done then &lt;CODE class=" language-jsl"&gt;self&lt;/CODE&gt; now refers to a different variable and chaos ensues.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The &lt;CODE class=" language-jsl"&gt;Local()&lt;/CODE&gt; function creates a local block and any variables defined in the first argument (the list) are local to that block, such as&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;Names Default to Here( 1 );
a = 1;
b = 4;
Print( "Before Local Block:" );
Show( a, b );
Local(
	{local_var1, local_var2, b},
	local_var1 = 4;
	local_var2 = 2;
	b = 9;
	Print( "Inside Local Block:" );
	Show( local_var1, local_var2, a, b );
	a = 5;
);
Print( "After Local Block:" );
Show( Try( local_var1, Empty() ), Try( local_var2, Empty() ), a, b )
/*:

"Before Local Block:"
a = 1;
b = 4;
"Inside Local Block:"
local_var1 = 4;
local_var2 = 2;
a = 1;
b = 9;
"After Local Block:"
Try(local_var1, Empty()) = Empty();
Try(local_var2, Empty()) = Empty();
a = 5;
b = 4;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;Here I redefine both &lt;CODE class=" language-jsl"&gt;a&lt;/CODE&gt; and &lt;CODE class=" language-jsl"&gt;b&lt;/CODE&gt; inside the local block, but &lt;CODE class=" language-jsl"&gt;b&lt;/CODE&gt; outside the local block is not affected while &lt;CODE class=" language-jsl"&gt;a&lt;/CODE&gt; is.&amp;nbsp; Putting &lt;CODE class=" language-jsl"&gt;self&lt;/CODE&gt; as a local variable is the safest approach.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 24 May 2022 21:51:11 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/Need-help-understanding-how-variables-are-scoped-in-expressions/m-p/492019#M73325</guid>
      <dc:creator>ErraticAttack</dc:creator>
      <dc:date>2022-05-24T21:51:11Z</dc:date>
    </item>
  </channel>
</rss>

