cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
JMP is taking Discovery online, April 16 and 18. Register today and join us for interactive sessions featuring popular presentation topics, networking, and discussions with the experts.
Choose Language Hide Translation Bar
Craige_Hales
Super User
Introspection

tree8786.jpg

JMP's scripting language, JSL, is built out of function calls. Pretty much everything you can write in JSL is a function call. Some things don't look like function calls:

A = A + 3;

It's pretty obvious the right-hand-side of the assignment statement is an expression. It's less obvious the assignment statement itself is an expression.

E = expr ( A = A + 3 );

expr is a wrapper that you can use around an expression to prevent the expression from evaluating. E is set to the expression, not the expression's evaluated result. To take a peek at E, use the head function. Head will return the name of the function at the root of the expression:

show( head(E) );

Head(E) = Assign();

Now you see there is a function for making assignments:

Assign( testing, 3+4 );

7

show(testing)

testing = 7;

Expressions in JSL are actually trees. Here's a picture of the a=a+3 tree, root at top, leaves at bottom:

tree.png

Similar to the Head function, we can use the Arg function to access the children of the Assign function:

show( arg(E,1) );

Arg(E, 1) = A; the left-hand side

show( arg(E,2) );

Arg(E, 2) = A + 3; the right-hand side

and digging deeper,

show(head(arg(E,2)))

Head(Arg(E, 2)) = Add();  the head of the right-hand side

show(arg(arg(E,2),1))

Arg(Arg(E, 2), 1) = A;  the left side of the plus

show(arg(arg(E,2),2))

Arg(Arg(E, 2), 2) = 3;  the right side of the plus

Notice how the parenthesis nesting describes the tree. This tree only has binary splits. There is a function, narg, that returns the number of children. It returns 0 for leaf nodes. 

narg(E)

2  the assign function has two arguments, the left-hand side and the right-hand side

JMP's for statement is a function call, taking four arguments. Notice the commas separating the arguments, just like any other function.

halfCats = 1;
for( iCat = 1, iCat <= 10, iCat++, 
   halfCats = halfCats / 2; 
   write( iCat, " ", halfCats , "\!n" ) 
);

1 0.5

2 0.25

3 0.125

4 0.0625

5 0.03125

6 0.015625

7 0.0078125

8 0.00390625

9 0.001953125

10 0.0009765625

It takes three commas to separate four arguments. In this for statement, the fourth argument is two statements, separated by a semicolon. Peek at the fourth argument to see if it is actually a function too:

Head(
    Arg(
        Expr(
            For( iCat = 1, iCat <= 10, iCat++,  
               halfCats = halfCats / 2;  
               Write( iCat, " ", halfCats, "\!n" );  
            )
        ), 
        4 /* the fourth arg */
    )
);

Glue() 

Glue is the name of the function that holds a sequence of statements together.  Glue's first argument is the first statement, etc.

Arg(
    Arg(
        Expr(
            For( iCat = 1, iCat <= 10, iCat++,  
               halfCats = halfCats / 2;  
               Write( iCat, " ", halfCats, "\!n" );  
            )
        ), 
        4 /* the fourth arg is two statements, glued together */
    ), 
    1 /* the first arg is the first of the two glued statements */
);

halfCats = halfCats / 2

A JSL list is the same sort of expression:

list={33,44,55};
show(head(list));
show(narg(list));
show(arg(list,3));

Head(list) = {};  list displays curly brackets for the head, rather than a name like Assign

N Arg(list) = 3;

Arg(list, 3) = 55;

If you just want the contents of the list, you should use normal subscripting:

show(list[3]);

list[3] = 55;

But sometimes you want to do something like turning a list into arguments to a function.

In the Elephant post you'll find an example of turning a list into a pattern (line 5). I'm having a hard time coming up with another example as cool as that one, but suppose you wanted to check if the list was in alphabetical order. JMP's < operator can do that in a single function call:

LT = expr("a"<"b"<"c"<"d");
show(head(LT));
show(narg(LT));

Head(LT) = Less();  the less-than operator displays a function name, Less

N Arg(LT) = 4;

The Less function can take a lot of arguments, but you don't have to type them. Below, NameExpr is retrieving the expresion stored in words, after the SubstituteInto modified the { list } to be Less(). JMP then displays the Less function using < to make it more readable. 

words =
{"Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf", "Hotel", "India",
"Juliet", "Kilo", "Lima", "Mike", "November", "Oscar", "Papa", "Quebec", "Romeo",
"Sierra", "Tango", "Uniform", "Victor", "Whiskey", "Xray", "Yankee", "Zulu"};
Substitute Into( words, Expr( {} ), Expr( Less() ) );
nameExpr(words);

"Alpha" < "Bravo" < "Charlie" < "Delta" < "Echo" < "Foxtrot" < "Golf" < "Hotel" <

"India" < "Juliet" < "Kilo" < "Lima" < "Mike" < "November" < "Oscar" < "Papa" <

"Quebec" < "Romeo" < "Sierra" < "Tango" < "Uniform" < "Victor" < "Whiskey" < "Xray" < "Yankee" < "Zulu"

eval(words)

eval(words) returns 1, indicating the result of Less was true.

Another example.

Update 28Feb2017 - repair formatting for new community

Last Modified: Feb 28, 2017 1:20 PM
Comments
Jeff_Perkinson
Community Manager
Craige_Hales
Super User

Thanks.  Joseph covers a lot more than I did.

Hui_Di
Staff

Very good piece to understand the nature of JSL and list.

hlrauch
Level III

Craig, this article was very helpful to me in my continuing quest to understand how to deal with expressions.

I actually had a good application for your final trick, where you turned items in a list into arguments of the Less() function. I wanted to generate a column formula containing the Col Mean() function, based on user input from a dialog window. The Col Means() function takes one or more arguments, and I've never had a slick way to substitute a varying number of arguments (often variable names) into a function. Here are the key lines in my script:

arglist = {"height", "age", "sex"}; // results from a dialog window

statformula = Substitute ( arglist, Expr( {} ), Expr( Col Mean() ) ); // items in arglist become arguments in Col Means() function

newcol << Formula( Name Expr( statformula ) );

The actual script is more complex because it needs to deal with messy column names that require Name(" "), but you get the idea. Thanks for showing me this neat trick.

Howard Rauch

Craige_Hales
Super User

Welcome, and thanks!  Your example is way better than my Less example.

Craige