Our World Statistics Day conversations have been a great reminder of how much statistics can inform our lives. Do you have an example of how statistics has made a difference in your life? Share your story with the Community!
Choose Language Hide Translation Bar
Staff (Retired)
Introspection

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:

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:

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(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:

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(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(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.

Update 28Feb2017 - repair formatting for new community

Article Labels

There are no labels assigned to this post.

Article Tags
Community Manager
Staff (Retired)

Thanks.  Joseph covers a lot more than I did.

Staff

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

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

Staff (Retired)

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

Craige