Subscribe Bookmark RSS Feed

Throw() inside include/function

msharp

Super User

Joined:

Jul 28, 2015

I have a piece of code that is used by many scripts, so I have transferred it to an include file.  This code does a check and throws if it fails.  However, I'm finding that it only kills the script that is running inside the include, after which it picks up and starts running the code that originally called the include.  This kind of behavior I'm going to call a soft kill.  I need the throw() that is included to kill "both" scripts.

Soft kills are typical in other languages but run inside functions, this way you can have a piece of code fail silently.  However, it seems throw() inside a function actually hard kills all script running. 

Example:

throwTest.jsl

Print("A");

Include("~path\throwTest.include.jsl");

Print("D");

throwTest = Function({}, {Default Local},

       Print("E");

       throw();

       Print("F");

);

throwTest();

Print("G");


throwTest.include.jsl

Print("B");

throw();

Print("C");


Log output:

"A" "B" "D" "E"


Does anyone know how to hard kill JSL from inside an included script?

1 ACCEPTED SOLUTION

Accepted Solutions
Solution

JMP 13 (scheduled for September) addresses this; the fix will require you to add try(...) around the include.  (try does not catch a throw from an include in 12.2).  Without the try, JMP 13 will behave the same as 12.2.

JMP 13:

Print("A");

try( Include("$desktop\throwTest.include.jsl"),print("catch"));

Print("D");

throwTest = Function({}, {Default Local},

       Print("E");

       throw();

       Print("F");

);

throwTest();

Print("G");

"A" "B" "catch" "D" "E"

Craige
7 REPLIES
txnelson

Super User

Joined:

Jun 22, 2012

I believe you can solve this issue with a simple passing of information via a check variable and take action in the main script.

 

Names Default To Here( 1 );

 

Include( "C:\Users\txjim\Documents\JMP\throwTest.include.jsl" ); 

If( throwit == 1, Throw() ); 

Print( "D" );

 

throwTest = Function( {},

       {Default Local},

       Print( "E" ); 

       Throw(); 

       Print( "F" ); 

);

 

throwTest();

Print( "G" );

   

// Here is the include file 

Print( "B" ); 

throwit = 1;

Throw();

Print( "C" );

 

Jim
msharp

Super User

Joined:

Jul 28, 2015

While this is a simple work around, it really defeats the purpose of using an include.

txnelson

Super User

Joined:

Jun 22, 2012

I have to disagree with your statement that the above method "defeats the purpose of using an include".

Included code can be performing many, many different types of functions, and doing lots of things like data cleansing, transformations, etc.  If within the included code, an invalid usage case is discovered, one might want to shut down the whole application.  Therefore, one would need to Throw the included code, and then when execution is passed back to the main code, one would need to detect that the fail situation has been detected, and then would need to throw the main script.

Jim
msharp

Super User

Joined:

Jul 28, 2015

I see things differently.

If all you want to do is run "lots of things", "many different types of functions" there is nothing stopping you from putting many functions in one script.  You can even do error checks and stop functions from running without throwing the whole script. --see my Return() script below.

The purpose of includes is to reduce the amount of times you have to code the exact same script.
If I have 100 different scripts, all of which define a=1; b=2; c=3; ... so on to zz=702, you wouldn't want to type this all out 100 times.  Without includes, most likely you would type it once and copy and paste into your other scripts.  But what if down the line you find a bug?  You'd have to go into 100 scripts and manually fix the code.  A tedious job.  But what if you end up finding a faster way to perform the same task of defining all these variables?  You'd have to refactor your code 100 times across all the scripts.  What if you decide you actually want a=2; b=3... ect.  You'd have to change your code 100 times.  Changing 100 scripts is an error prone task, what if you miss a script, make a wrong change, ect? 
The purpose of includes is not to create a slave/master relationship where you can kill the slave and save the master.  We have functions for that.  The purpose of includes is to save time coding.

(Note: Another purpose of includes is to help keep scripting languages separate making it easy to debug and keep code clean.  Includes are especially helpful in web applications with HTML/CSS/JavaScript, but this doesn't really apply to JSL.)

Passing a check variable has a few problems not many but a few.  What if another script uses the same check variable?  What if I decide to change the check variable?  What if I mistyped the check variable? In each case, I'd then have to go and find every script I included the throwTest.include and edit the check variable to be correct, which defeats the purpose of using the include in the first place.

msharp

Super User

Joined:

Jul 28, 2015

Update, not sure why I didn't think of this last night, but sending the return() statement early will effectively throw a function.  This is a common in other languages as well.

throwTest = Function({}, {Default Local},

       Print( "E" );

       Return();

       Print( "F" );

);

throwTest();

Print( "G" );

Output:

"E" "G"

Solution

JMP 13 (scheduled for September) addresses this; the fix will require you to add try(...) around the include.  (try does not catch a throw from an include in 12.2).  Without the try, JMP 13 will behave the same as 12.2.

JMP 13:

Print("A");

try( Include("$desktop\throwTest.include.jsl"),print("catch"));

Print("D");

throwTest = Function({}, {Default Local},

       Print("E");

       throw();

       Print("F");

);

throwTest();

Print("G");

"A" "B" "catch" "D" "E"

Craige
msharp

Super User

Joined:

Jul 28, 2015

Awesome thanks Craige@JMP​!  I will look forward to JMP 13 then.