All rights reserved. Produced in the United States of America.
For a hard-copy book: No part of this publication may be reproduced, stored in a retrieval system, or
transmitted, in any form or by any means, electronic, mechanical, photocopying, or otherwise, without
the prior written permission of the publisher, SAS Institute Inc.
For a Web download or e-book: Your use of this publication shall be governed by the terms established
by the vendor at the time you acquire this publication.
U.S. Government Restricted Rights Notice: Use, duplication, or disclosure of this software and related
documentation by the U.S. government is subject to the Agreement with SAS Institute and the
restrictions set forth in FAR 52.227-19, Commercial Computer Software-Restricted Rights (June 1987).
SAS Institute Inc., SAS Campus Drive, Cary, North Carolina 27513.
1st printing, September 2010
2nd printing, January 2011
®
JMP
, SAS® and all other SAS Institute Inc. product or service names are registered trademarks or
trademarks of SAS Institute Inc. in the USA and other countries. ® indicates USA registration.
Other brand and product names are registered trademarks or trademarks of their respective companies.
Get the Most from JMP
Whether you are a first-time or a long-time user, there is always something to learn about JMP.
Visit JMP.com to find the following:
•live and recorded Webcasts about how to get started with JMP
•video demos and Webcasts of new features and advanced techniques
•schedules for seminars being held in your area
•success stories showing how others use JMP
•a blog with tips, tricks, and stories from JMP staff
JMP was developed by SAS Institute Inc., Cary, NC. JMP is not a part of the SAS System, though portions
of JMP were adapted from routines in the SAS System, particularly for linear algebra and probability
calculations. Version 1 of JMP went into production in October 1989.
Credits
JMP was conceived and started by John Sall. Design and development were done by John Sall, Chung-Wei
Ng, Michael Hecht, Richard Potter, Brian Corcoran, Annie Dudley Zangi, Bradley Jones, Craige Hales,
Chris Gotwalt, Paul Nelson, Xan Gregg, Jianfeng Ding, Eric Hill, John Schroedl, Laura Lancaster, Scott
McQuiggan, Melinda Thielbar, Clay Barker, Peng Liu, Dave Barbour, Jeff Polzin, John Ponte, and Steve
Amerige.
In the SAS Institute Technical Support division, Duane Hayes, Wendy Murphrey, Rosemary Lucas, Win
LeDinh, Bobby Riggs, Glen Grimme, Sue Walsh, Mike Stockstill, Kathleen Kiernan, and Liz Edwards
provide technical support.
Nicole Jones, Kyoko Keener, Hui Di, Joseph Morgan, Wenjun Bao, Fang Chen, Susan Shao, Michael
Crotty, Jong-Seok Lee, Tonya Mauldin, Audrey Ventura, Ani Eloyan, Bo Meng, and Sequola McNeill
provide ongoing quality assurance. Additional testing and technical support are provided by Noriki Inoue,
Kyoko Takenaka, Yusuke Ono, Masakazu Okada, and Naohiro Masukawa from SAS Japan.
Bob Hickey and Jim Borek are the release engineers.
The JMP books were written by Ann Lehman, Lee Creighton, John Sall, Bradley Jones, Erin Vang, Melanie
Drake, Meredith Blackwelder, Diane Perhac, Jonathan Gatlin, Susan Conaghan, and Sheila Loring, with
contributions from Annie Dudley Zangi and Brian Corcoran. Creative services and production was done by
SAS Publications. Melanie Drake implemented the Help system.
Jon Weisz and Jeff Perkinson provided project management. Also thanks to Lou Valente, Ian Cox, Mark
Bailey, and Malcolm Moore for technical advice.
Thanks also to Georges Guirguis, Warren Sarle, Gordon Johnston, Duane Hayes, Russell Wolfinger,
Randall Tobias, Robert N. Rodriguez, Ying So, Warren Kuhfeld, George MacKensie, Bob Lucas, Warren
Kuhfeld, Mike Leonard, and Padraic Neville for statistical R&D support. Thanks are also due to Doug
Melzer, Bryan Wolfe, Vincent DelGobbo, Biff Beers, Russell Gonsalves, Mitchel Soltys, Dave Mackie, and
Stephanie Smith, who helped us get started with SAS Foundation Services from JMP.
Acknowledgments
We owe special gratitude to the people that encouraged us to start JMP, to the alpha and beta testers of JMP,
and to the reviewers of the documentation. In particular we thank Michael Benson, Howard Yetter (d),
xviii
Andy Mauromoustakos, Al Best, Stan Young, Robert Muenchen, Lenore Herzenberg, Ramon Leon, Tom
Lange, Homer Hegedus, Skip Weed, Michael Emptage, Pat Spagan, Paul Wenz, Mike Bowen, Lori Gates,
Georgia Morgan, David Tanaka, Zoe Jewell, Sky Alibhai, David Coleman, Linda Blazek, Michael Friendly,
Joe Hockman, Frank Shen, J.H. Goodman, David Iklé, Barry Hembree, Dan Obermiller, Jeff Sweeney,
Lynn Vanatta, and Kris Ghosh.
Also, we thank Dick DeVeaux, Gray McQuarrie, Robert Stine, George Fraction, Avigdor Cahaner, José
Ramirez, Gudmunder Axelsson, Al Fulmer, Cary Tuckfield, Ron Thisted, Nancy McDermott, Veronica
Czitrom, Tom Johnson, Cy Wegman, Paul Dwyer, DaRon Huffaker, Kevin Norwood, Mike Thompson,
Jack Reese, Francois Mainville, and John Wass.
We also thank the following individuals for expert advice in their statistical specialties: R. Hocking and P.
Spector for advice on effective hypotheses; Robert Mee for screening design generators; Roselinde Kessels
for advice on choice experiments; Greg Piepel, Peter Goos, J. Stuart Hunter, Dennis Lin, Doug
Montgomery, and Chris Nachtsheim for advice on design of experiments; Jason Hsu for advice on multiple
comparisons methods (not all of which we were able to incorporate in JMP); Ralph O’Brien for advice on
homogeneity of variance tests; Ralph O’Brien and S. Paul Wright for advice on statistical power; Keith
Muller for advice in multivariate methods, Harry Martz, Wayne Nelson, Ramon Leon, Dave Trindade, Paul
Tobias, and William Q. Meeker for advice on reliability plots; Lijian Yang and J.S. Marron for bivariate
smoothing design; George Milliken and Yurii Bulavski for development of mixed models; Will Potts and
Cathy Maahs-Fladung for data mining; Clay Thompson for advice on contour plotting algorithms; and
Tom Little, Damon Stoddard, Blanton Godfrey, Tim Clapp, and Joe Ficalora for advice in the area of Six
Sigma; and Josef Schmee and Alan Bowman for advice on simulation and tolerance design.
For sample data, thanks to Patrice Strahle for Pareto examples, the Texas air control board for the pollution
data, and David Coleman for the pollen (eureka) data.
Translations
Trish O'Grady coordinates localization. Special thanks to Noriki Inoue, Kyoko Takenaka, Masakazu Okada,
Naohiro Masukawa, and Yusuke Ono (SAS Japan); and Professor Toshiro Haga (retired, Tokyo University
of Science) and Professor Hirohiko Asano (Tokyo Metropolitan University) for reviewing our Japanese
translation; François Bergeret for reviewing the French translation; Bertram Schäfer and David Meintrup
(consultants, StatCon) for reviewing the German translation; Patrizia Omodei, Maria Scaccabarozzi, and
Letizia Bazzani (SAS Italy) for reviewing the Italian translation; RuiQi Qiao, Rula Li, and Molly Li for
reviewing Simplified Chinese translation (SAS R&D Beijing); Finally, thanks to all the members of our
outstanding translation and engineering teams.
Past Support
Many people were important in the evolution of JMP. Special thanks to David DeLong, Mary Cole, Kristin
Nauta, Aaron Walker, Ike Walker, Eric Gjertsen, Dave Tilley, Ruth Lee, Annette Sanders, Tim Christensen,
Eric Wasserman, Charles Soper, Wenjie Bao, and Junji Kishimoto. Thanks to SAS Institute quality
assurance by Jeanne Martin, Fouad Younan, and Frank Lassiter. Additional testing for Versions 3 and 4 was
done by Li Yang, Brenda Sun, Katrina Hauser, and Andrea Ritter.
Also thanks to Jenny Kendall, John Hansen, Eddie Routten, David Schlotzhauer, and James Mulherin.
Thanks to Steve Shack, Greg Weier, and Maura Stokes for testing JMP Version 1.
Thanks for support from Charles Shipp, Harold Gugel (d), Jim Winters, Matthew Lay, Tim Rey, Rubin
Gabriel, Brian Ruff, William Lisowski, David Morganstein, Tom Esposito, Susan West, Chris Fehily, Dan
Chilko, Jim Shook, Ken Bodner, Rick Blahunka, Dana C. Aultman, and William Fehlner.
Technology License Notices
xix
Scintilla is Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>.
This introduction shows you the basics of JMP Scripting Language (JSL). The chapter starts with a simple,
progressive tutorial example to show you where to type a script, how to submit it, and how to modify and
save it. The purpose of this tutorial is to give you the basic techniques for working with any script, whether
it’s one you write or one you get from someone else. Next is a showcase of examples to demonstrate how
scripting might be useful in a variety of settings. For example, classroom simulations, advanced data
manipulations, custom statistics, production lines, and so forth.
Confusion alert! Throughout this book, special shaded “confusion alerts” like this one
call your attention to important concepts that could be unfamiliar or more
complicated than you might expect, or where JMP might be a little different from
other applications. These alerts appear whenever a particularly good example of a
potential problem arises in the text, and although you will find them under topics that
might not apply to your immediate needs, the ideas presented are always general and
important. Please be sure to take a look even when you are skipping pages and looking
for something else.
You can quickly locate these pointers by looking up “confusion alert” in the “Index,”
p. 713.
This exercise is simple and hearkens back to a classic. Perhaps you recognize it.
1. Start JMP.
2. If the log window is not open, open it by selecting
Macintosh.
3. In the JMP Starter window, click
New Script.
New scripts can also be created from the menus. On Windows, select
Macintosh, select
File>New>NewScript.
4. In the resulting script editor, type these lines:
A = "Hello, World";
Show( A );
5. From the Edit menu, select Run Script.
The keyboard shortcut is to press CTRL-R on Windows or COMMAND-R on Macintosh.
The result is shown in the Log window. Besides showing results and errors, this window is also a script
editor.
View > Log on Windows or Window > Log on
File > New > Script. On
Figure 1.1 The Script Window (left) and the Log Window (right)
This is how you enter and submit JSL. You have just created a global variable named A, assigned a value to
it, and shown its value. Notice that the log echoes your script first, and then echoes any results. In this case,
the result is the output for the
Show(A) command.
Go To Line
As your scripts grow in size, it is handy to jump to specific lines in the script. Use the
from the
Edit menu to jump to a specific line.
Go To Line command
4Introducing JSLChapter 1
Hello, World
This command is also useful during the debugging process, since error messages frequently mention the line
of the script where the error occurred.
Show Line Numbers
The script window does not show line numbers by default. To see the line numbers, right-click anywhere in
the script window, and then select
Show Line Numbers.
Modify the Script
Now try making this script do a little more work by adding a For-loop to greet the world not just once, but
four times. Also, use
For-loop works.
1. In the script window, change the script to this:
For( i = 1, i < 5, i++,
X = i;
A = "Hello, World";
Print( X, A );
);
Print( "done" );
2. Submit the script as before.
(To submit part of the text in a window instead of all text, select the text first and then press Control-R
on Windows or a-R on Macintosh)
Print this time instead of Show, and make a few other changes to see how the
Output
1
"Hello, World"
2
"Hello, World"
3
"Hello, World"
4
"Hello, World"
"done"
Print
is similar to Show except that it does not label the results with the variable name. It just prints the
value.
Stopping a Script
When you run a script, the
is running, you can select this option to stop it. You can also press ESC on Windows or
COMAND-PERIOD on Macintosh . Many scripts execute more quickly than you can stop them.
Run Script command in the Edit menu changes to Stop Script. While a script
Chapter 1Introducing JSL5
Hello, World
Punctuation and Spaces
Notice the indented lines inside the
For-loop. This is not necessary for JMP’s sake; it just makes it a little
easier to read. You could write this script like this if you want:
fo R(i=
1,i<5,i++
,X=i;A="Hello, World";P r i N T(X,A));print("done");
Words in JMP’s scripting language are separated by parentheses, commas, semicolons, and various operators
such as +, –, and so on. As far as JMP is concerned, spaces, tabs, returns, and blank lines inside or between
operators or within JSL words do not exist. This is because most JSL words come from JMP’s usual
graphical user interface (GUI), and most of those commands have spaces in them. For example, you will see
later on that to do Fit Model, the JSL would be
parentheses)
. Most people would rather see “Fit Model” than “fitmodel.”
Fit Model(and some arguments inside
JSL is not case-sensitive, so you do not have to worry about reaching for the Shift key all the time.
You do have to be a little careful inside a text string. In “Hello, World” extra spaces would affect the output,
because text strings inside double quotation marks are taken literally, exactly as you type them. Also, you
would get errors if you put spaces between the two plus signs in
same as
43).
i++, (i+ +), or in numbers (43 is not the
Generally, JSL uses:
commas , between arguments inside the parentheses for a command.
parentheses ( ) to surround all the arguments of a command. Many JSL words have parentheses after
them even if they do not take arguments; for example
the number 3.14...
do give it. Therefore,
Pi does not expect an argument and will complain about any argument that you
Pi(mincemeat) would be considered an error (although it seems heretical to
pi() has the parentheses even though π is just
say so). But the parentheses are still required.
semicolons ; to separate commands but also to glue them together. In other words, you use a
semicolon to separate one complete message from the next. For example,
semicolon really does is tell JMP to continue and do more things. For example, the
a=1;b=2. What the
For-loop
example showed how to put several statements in the place of one statement for the fourth
argument, because the semicolon effectively turned all three statements into one argument.
Trailing semicolons (extras at the end of a script or at the end of a list of arguments) are harmless, so
you can also think of semicolons as terminating characters. In fact, terminating each complete JSL
statement with a semicolon is a good habit to adopt.
quotation marks " " to enclose text strings. Anything inside quotation marks is taken literally,
exactly as is, including spaces and upper- or lower-case. Nothing that could be evaluated is evaluated.
If you have
pi()^2 inside quotation marks, it is just a sequence of six characters, not a value close to
ten. See “Quoted Strings,” p. 28, for ways to include special characters and quotation marks in
strings.
For a more formal discussion of punctuation rules, see “Lexical Rules of the Language,” p. 26.
6Introducing JSLChapter 1
Saving and Sharing Your Work
Save a Script
To save your script, just follow these instructions:
1. Make the script window active (click the “Untitled” window to make it the front-most window).
2. From the
3. Specify a filename, including the extension
4. Click
Scripts are saved as text files, and you can edit them with any text editor. However, if you do edit scripts
with applications other than JMP, be careful to save them as plain text files. If you preserve the
you can double-click a script file to launch JMP.
File menu, select Save or Save As.
.jsl. For example, hello.jsl.
Save.
.jsl extension,
To reuse a script, use
Open from JMP’s File menu, double-click a .jsl file, or drag and drop the file onto
JMP’s application icon.
When opening a JSL file, the actual script is always opened in its own script window. However, it might be
distracting to some users to see this window. To keep a script from opening in a script window, put this
command on the first line of the script.
//!
If it is not on the very first line by itself, this command does nothing.
You can over-ride this comment when opening the file. Select
select the JSL file and click
Open. The script opens into a script window instead of being executed.
Save the Log
You can also save logs as text files, which can be viewed with any text editor. Double-clicking a log file does
not launch JMP.
1. Make the log window active (click the Log window to make it the front-most window).
2. From the
File menu, select Save or Save As.
3. Specify a filename, including the extension .txt on Windows. For example, hello.txt.
4. Click Save
Saving and Sharing Your Work
File > Open. Hold the CTRL key while you
Here is something just about everybody will find useful sooner or later: JMP can create scripts to duplicate
your data tables and analyses. For example:
•Suppose you need to describe an analysis process in detail, from beginning to end, such as to create an
audit trail for a governing agency or for peers reviewing your journal article.
•Suppose you have a set of analysis steps that should be followed routinely by your lab technicians.
•Suppose you fit the same model to new data every day, and you are tired of clicking the same buttons
over and over again.
Chapter 1Introducing JSL7
Saving and Sharing Your Work
•Suppose you are working with somebody in another city who cannot simply look over your shoulder to
see how you put something together.
You can use JMP interactively as usual, save scripts to reproduce your work, and in the future just run those
scripts. Next are some examples showing how this works.
Capturing Scripts for Data Tables
1. Open a data table and make all types of changes. For example, add rows and columns, change values,
rearrange columns, sort the rows, make a formula column, make a row state column, and so on.
2. When you are finished, open a script window and type this:
current data table()<<get script;
3. In the Script window, click and drag to select (highlight) the script.
4. Run the script and look at the output shown in the Log window:
From the
Figure 1.2 The Get Script Command and the Log
Edit menu, select Run Script.
Now try running the script in the log window:
1. In the Log window, click and drag to select (highlight) the script, starting with
with the last line in the log.
2. From the
Edit menu, select Run Script.
New Table and ending
8Introducing JSLChapter 1
Saving and Sharing Your Work
The script produces a perfect clone of your data table.
Capturing Scripts for Analyses
Launch a platform, such as Fit Model. Look at the default results and then go exploring. Try options to see
related tests and graphs. Work with the red triangle menus in the report surface to get exactly the report that
you want.
When you are finished, get a script to recreate your results. There are two methods of getting a script for
your results. One is to use the Script menu located at the bottom of each platform’s red triangle menu. This
method is detailed in “Use JMP Interactively to Learn Scripting,” p. 11.
1. First you need to figure out what JMP calls your analysis. This can be tricky in some cases, as discussed
in the “Scripting Platforms” chapter, but usually you can read it from the title of the analysis window,
after the name of the data table. For example, the platform for a window titled “Big Class: Fit Least
Squares” would be called
2. Now you have to specify a part of the report. You might have fit several models before getting the one
that you want to keep. You need to tell JMP which one you want by supplying a subscript, which is just
a number inside brackets after the name. If the third model that you fit is the one that you want, you
would specify it as
3. You are ready to get the script from the object:
Fit Least Squares[3] << get script;
Fit Least Squares.
Fit Least Squares[3].
The results might look something like this, depending on which steps you performed:
Fit Model(
Y( :weight ),
Effects( :sex, :height, :sex * :height ),
Personality( Standard Least Squares ),
Run Model(
Profiler(
Confidence Intervals( 1 ),
Desirability Functions( 1 )
),
Contour Profiler(
Surface Plot( 1 )
)
)
)
Tr y r un ni n g th e s c ri p t:
1. In the Log window, click and drag to select (highlight) the script
2. From the
Edit menu, select Run Script.
The script produces a perfect clone of your analysis. If you want a journal, use this command:
Fit Least Squares[1] << journal window;
Chapter 1Introducing JSL9
Saving and Sharing Your Work
A General Method for Creating Scripts
1. Did you use an existing data table as is? Write an Open statement for it:
dt = Open( "$SAMPLE_DATA/Big Class.JMP" );
2. Did you create a new table or make changes to an existing data table? Did you work with row states,
such as to color and label points in your plots? Did you exclude some rows? Did you fix errors? If so, you
should get a script to recreate your data table.
Current Data Table() << get script;
3. Which platforms did you launch, work with, and keep for your final results? Get scripts to recreate
them. You will learn the details in the “Scripting Platforms” chapter; here you will just try some
examples.
Bivariate[1] << get script;
Fit Least Squares[1] << get script;
4. Now edit the log into a complete script. Be sure to put semicolons ( ; ) in between statements. You
might have something like this:
New Table( "Big Class",
Add Rows( 40 ),
New Column( "name",
Character,
Nominal,
Set Property( Notes, "...usually used as a label variable in plots" ),
Values(
6. If you share your JSL file with your colleagues, be sure to include any data tables or additional files along
with the script.
Use JMP Interactively to Learn Scripting
One of the simplest ways to accomplish anything is to get somebody else to do it for you, and writing JSL is
no exception. The best JSL writer is JMP itself. This example shows how to work in JMP interactively and
then save the results as a script to reuse later on. With simple modifications, this script can serve as a
template for speeding up routine tasks.
What JMP Can and Cannot do to Help You Write Scripts
JMP can automatically save scripts to reproduce any data table or analysis in its current state. You can pause
any time in your analysis to save a script to a script window, in a data table, or in an analysis report. You can
then modify the automatically generated script as needed for future projects.
JMP cannot record scripts while you are working. While script-recording is a useful feature in some other
scripting languages, it is less important for a program like JMP, where the important thing is the results. You
cannot use script-recording to observe how a sequence of interactive steps is performed.
However, remember that you can save a script when you are finished, and that script reproduces everything
that you have accomplished.
JMP’s scripting language is not intended to be an alternative command-line interface for using the program.
JSL is intended for recreating results and for extending JMP’s capabilities beyond JMP’s intended use in data
discovery.
There is More Than One Way
Since JSL is a very flexible language, you can accomplish things many different ways.
Typically the script that JMP saves for you specifies every detail of your analysis, even if most of the details
happen automatically by default. Does that mean that the scripts that you write have to be just as complete
and detailed? Not at all. You usually just need to specify the details that you would specify when using the
graphical user interface (GUI). For example, if you open
height, weight, and sex, you would need only to do this in JSL:
Distribution( Y( :height, :weight, :sex ) );
But if you select Script > Save Script to Script Window from the red triangle menu for the report, you
would see this:
Both methods give the same result. Feel free to experiment with JSL. If you think something ought to be
possible, it probably is. Give it a try, and see what happens.
Using the Script Editor and Debugger
JMP provides both an editor and a debugger for writing and troubleshooting your JSL scripts.
The Script Editor
The Script Editor (as shown in Figure 1.3) provides a friendly environment for writing and reading JSL
scripts.
Figure 1.3 The Script Editor
The script editor has several useful features:
•color-coding for JSL and SAS code
•autocompletion for JSL functions (press CONTROL-SPACE on Windows or COMMAND-SPACE
on Macintosh)
•tooltips when hovering over JSL functions
Chapter 1Introducing JSL13
Saving and Sharing Your Work
•value-reporting when hovering over a global symbol
•live brace matching
•highlighting matching braces
•find and replace using regular expressions
•automatic formatting
The script editor is also used in the log window and anywhere else you can edit or write a script.
Color-Coding
The script window uses the following colors for JSL:
•green for comments
•blue for JSL functions
•dark magenta for string values
•dark cyan and bold for scalar values
•black for everything else
Colors can be customized in Preferences. See “Setting Preferences for the Script Editor,” p. 15.
Auto-Completion
If you do not remember the exact name of a function, you can type part of the name and then press
CONTROL-SPACE or CONTROL-ENTER on Windows, or ESC on Macintosh to see a list of functions
that match what you have typed so far.
For example, if you want to clear your JSL variables, but do not remember the command, you can type
clear, then CONTROL-SPACE, to see a list of possible clear commands.
Figure 1.4 Autocomplete Example
Select the command that you want to use.
Tooltips
If you are using a function and do not remember its syntax or what it does exactly, you can hover over it to
get a brief explanation. This only works with JSL function names, not platform commands, messages, or
user-created functions. JSL function names are colored blue in the script editor.
14Introducing JSLChapter 1
Saving and Sharing Your Work
Figure 1.5 Tooltip for a JSL Function
The tooltip shows the grammar, any arguments, and a brief explanation of the function.
You can also hover over variable names to see their current value. If you hover over a variable before running
the script, no tip appears, because JMP does not yet know about it.
Example of a Tooltip for a JSL Variable
1. Enter and run the following line in a script window:
my_variable = 8;
2. Hover over the variable name after you run the line.
A tooltip shows the name of the variable and its value: 8.
3. Enter and run the following line:
my_variable = "eight";
4. Hover over the variable name after you run the line.
A tooltip shows the name of the variable and its value: “eight”.
Brace-Matching
The script editor helps you match parentheses, square brackets, and curly braces in the following ways:
•The matching closing brace is added when you type an opening brace.
•When you place your cursor next to either an opening or closing brace, it and its match are highlighted
in blue. If it does not have a match, it is highlighted in red.
•If you double-click a brace, everything between the matching braces is selected (including the braces).
•If you put your cursor within a statement and press CONTROL-] on Windows, or CONTROL-B on
Macintosh, the entire statement is selected (including the braces that define it).
Figure 1.3 “The Script Editor,” p. 12 shows highlighted matching braces in the third line of code.
When you type an opening brace, add code in between, and then type the closing brace, the script editor
skips the cursor over the brace it that added automatically for you. This prevents you from accidentally
adding an additional closing brace.
You can turn on and off the autocompletion of braces in the Preferences window. See “Setting Preferences
for the Script Editor,” p. 15 for details.
Chapter 1Introducing JSL15
Saving and Sharing Your Work
Find and Replace
The
Edit > Search menu options are now available in scripts. Searching and replacing is the same as for
data tables.
1. From the
2. In the
Edit menu, select Search > Find.
Find what field, enter the text that you want to search for.
3. If you want to find text and replace it, enter the replacement text in the
4. Select any other check boxes that you want to use.
5. Click
Find to find the next occurrence, or click Replace to replace the current occurrence and find the
next.
See the Using JMP book for details about the Search window.
Automatic Formatting
The script editor can format a script for easier reading. Any generated script (for example, by saving a
platform script) is automatically formatted with tabs and returns in appropriate places.
If you open or write a script that is poorly formatted (for example, older saved JMP scripts that might have
all commands strung together with no whitespace characters), you can have the script editor format it for
you.
From the
Edit menu, select Reformat Script.
Tip: This command alerts you if your script is badly formed (for example, if your parentheses are not
matched).
Setting Preferences for the Script Editor
Replace with field.
You can customize several parts of the script editor. Open the Preference Settings window by selecting
Preferences.
Setting the Fonts
1. Select the Fonts group.
2. Click
Mono to set the font for the script editor.
For more details about font preferences, see the Using JMP book.
File >
16Introducing JSLChapter 1
Saving and Sharing Your Work
Figure 1.6 Changing the Font for Script Windows
Setting editor preferences
On the Script Editor page, you can make many other customizations:
Use tabs Check this option to enable tabs in your scripts. If it is unchecked, any tab you type is
replaced by spaces. This is on by default.
Tab w id thEnter how many spaces a tab should indent. If you have disabled tabs, any tab you type is
replaced with the number of spaces specified. The default value is 4.
Extra space at bottom of document Check this option to enable scrolling the last line of a script to
the top of the script editor. This is on by default.
Auto-complete parentheses and braces Check this option to enable the script editor to
automatically add closing parentheses, square brackets, and curly braces when you type an opening
one. This is on by default.
Show line numbers Check this option to show the line numbers on the right side of the script editor.
This is off by default.
Show operator tips Check this option to see tooltips for JSL functions. This is on by default.
Show indentation guides Check this option to see faint vertical lines that mark indention. This is
on by default.
Show variable value tips Check this option to see tooltips for variable values. This is on by default.
Spaces inside parentheses Check this option to cause the script editor to add spaces between
parentheses, brackets, and braces and their contents for automatically formatted scripts. This is on
by default.
Chapter 1Introducing JSL17
Saving and Sharing Your Work
Spaces in operator names
within function names. For example, turning on this option results in
NewWindow. This is on by default.
Setting colors used in the editor
To set your own color for any of the listed types, click the color box and select your color. (See Figure 1.7.)
Figure 1.7 Color Selection
Scripting the Script Editor
The editor is also scriptable, meaning you can write a script to write, change, or get information from
another script. First, you need to make a reference to your script window. For example, here is code that
creates a new script window and assigns a reference to it to the variable
Check this option to cause the script editor to add spaces between words
New Window instead of
ww:
ww = New Window( "Script Test", <<script, "initial contents" );
The initial contents can be left off, so that you create a blank script window. Next, you need to get a
reference to the display box portion of the script window:
ed = ww[Script Box( 1 )];
Although there is only one script box object, you still must call it by number.
There is a variety of messages that you can send your script box object.
Ta bl e 1 .1 Messages for a Script Box Object
ed << get text();
Places all the text in the script window in a single
string.
ed << set text( "string" );
Removes all the text currently in the script window
and replaces it with the string argument.
ed << append text( "string" );
Adds the string argument to the end of the script
window.
ed << get line text( 2 );
Places only the text from the designated line in a
string.
18Introducing JSLChapter 1
Saving and Sharing Your Work
Ta bl e 1 .1 Messages for a Script Box Object (Continued)
ed << set line text( 2, "string" );
ed << get line count();
ed << get lines();
ed << reformat();
ed << run();
The JSL Debugger (Windows Only)
In the JSL debugger, you can run the entire script, or step through the script one line at the time. This
feature is available only Windows. If you run a script with the debug command, the script runs normally.
To use the debugger, the first line of the JSL script should be as follows:
/*debug step*/
Be sure to type it exactly as shown above, in the first line of the script, with no extra blanks (including extra
blanks within the comment). All letters must be lower case.
Removes the text currently in the designated line
and replaces it with the string argument.
Returns the number of lines in the script window
as an integer.
Returns all the text in the script window as a list of
strings, one line per string.
Reformats the script.
Runs the entire script in the script window.
Chapter 1Introducing JSL19
Saving and Sharing Your Work
Figure 1.8 JSL Debugger
The following tasks are possible in the debugger.
Run Without Debugger Closes the debugger windows and runs the script normally.
Step Steps through the script one command at a time. A green arrow shows the current command.
Run Runs the script from the current command.
Add Watch Adds a variable to the watch list, located at the bottom of the debugger window. Watched
variables display their values as the script runs.
Remove Watch Removes a watched variable.
You can add a breakpoint to the script by clicking in the area to the left of a JSL line (the same area where
the green arrow circulates). A red circle appears at that line, and the script pauses when the line is executed.
Click the circle to remove the breakpoint.
20Introducing JSLChapter 1
Help with JSL
Help with JSL
There are several places within JMP to get help writing or understanding a JSL script.
JSL Browsers
The Help menu contains indexes for browsing functions, objects, and display boxes in the scripting
language:
JSL Functions Shows information about all functions.
Object Scripting Shows scriptable objects and what messages each can interpret.
DisplayBox Scripting Shows the elements in results windows and their messages.
An entry in the JSL Functions Index includes the syntax and a brief explanation. Many entries also have
example code. The Topic Help button for each entry opens the Help system and shows you the entry for the
item in the “JSL Syntax Reference,” p. 439. See Figure 1.9 for the entry for
Figure 1.9 JSL Functions Index
If().
Chapter 1Introducing JSL21
Help with JSL
Show Commands
Show Commands lists all the scriptable objects and functions in the log window, producing a text report that
is equivalent to the Functions browser. The default argument (if none is given) is
all JSL commands:
DisplayBoxes (For display tree objects and messages that you can send to them. Note that some
objects are not scriptable.)
•
ScriptableObjects (Any objects that currently have instances.)
•
StatTerms (Places all the information in the Statistics Index into a JMP data table.)
•
All for all of the above.
Builtins, which shows
Try these commands and look in the log for the output.
Showing Translations
If you are running JMP in another language, you can get a table that shows all objects’ JSL commands in
English and the localized language.
Show Commands( translations );
This command creates a data table that lists commands, the English name, and the localized name.
Argument translations are enumerated after their commands in entries beginning with the (localized) word
Enumeration.
Show Properties
Show Properties lists the messages that can be sent to a scriptable object and produces a text report that
is equivalent to the
display.
Open( "$SAMPLE_DATA/Big Class.jmp" );
Show Properties( Current Data Table() );
Show Points [Boolean] [Default On]
Fit Mean [New Entity]
Fit Line [New Entity]
...
Show Properties( Report( Bivariate[1] ) ); //the platform's display tree
Close [Boolean]
Horizontal [Boolean]
Open All Below [Action]
Close All Below [Action]
...
Chapter 2
JSL Building Blocks
Learn the Basic Components of JSL
JMP is scripted by a very simple language called JMP Scripting Language, or JSL. You might not need to
ever learn JSL, because almost every feature in the product is accessible through a direct user interface, as
well as through the scripting language. Even if you use JSL, you can usually get JMP to write the scripts for
you rather than typing them in yourself. JSL is most useful to power users who want to extend JMP past its
normal operating realm, or in production settings to automate a regularly scheduled analysis.
JSL is used in many places in JMP internally.
•Column Formulas are implemented internally in JSL.
•Platforms are launched using JSL internally.
•Platforms are interactively modified using JSL internally.
•Some graphics are performed through JSL.
Confusion alert! As described in the section on logical operators, a single pipe symbol
(
|) represents a logical OR. In the interests of brevity, programming and scripting
manuals commonly use a
| to represent the word or when discussing alternative values.
For example, a filepath can be either absolute or relative. When you see an argument
to a filepath function as
•
absolute to indicate an absolute filepath or
•
relative to indicate a relative filepath.
More than two options can be strung together with an or pipe in this way.
So, when you see words separated with a
absolute|relative, this means that you enter either:
This example shows you how to enter a script in the script editor, run it, and see the output.
1. Select
2. Select
File > New > Script.
View > Log on Windows, or Window > Log on Macintosh.
3. In the script window that appears, enter the following text:
X = 12 + 8;
A = "Hello, World";
Show( X, A );
4. Select Edit > Run Script.
You can also press CONTROL-R on Windows, or COMMAND-R on Macintosh.
The result appears in the Log window.
X = 20;
A = "Hello, World";
You have just created two global variables, X and A, and assigned values to them.
The JSL Language
JSL consists entirely of nested message names, with message contents enclosed in parentheses:
Message Name ( argument 1, argument 2, ... )
JSL expressions hold data, manipulate data, and send commands to objects.
The meaning of JSL phrases is dependent on who the message is sent to. The same name might mean one
thing in one context and something entirely different in another context.
Almost anything that obeys certain punctuation rules, such as matching parentheses, is a valid JSL
expression, though it might not be understood by the object it is sent to.
Here is a valid JSL expression:
New Window( "A Window",
<<modal,
Text Box( "Hello, World" ),
Text Box( "-----" ),
Button Box( "OK" )
);
Notice the following:
•Names can have embedded blanks.
•Message contents are enclosed in parentheses, which must be balanced.
•Items are separated by commas.
•You can use upper-case and lower-case characters interchangeably.
26JSL Building BlocksChapter 2
The JSL Language
•Messages are commonly nested inside other messages.
Lexical Rules of the Language
The language consists of the following types of tokens. Each are discussed briefly in subsections below.
Note: when you have a sequence of commands to execute, you do not separate them with commas. Rather,
you glue them together with semicolons, as discussed under “Gluing Expressions Together,” p. 42.
Chapter 2JSL Building Blocks27
The JSL Language
Parentheses
Parentheses ( ) are used to group operations in an expression and to delimit arguments to a function, such as
in
root(49). Parentheses also delimit the end of a function name even when arguments are not needed.
Consider
e( ) below, where the empty argument “()” after “e” is what distinguishes JSL’s function for e
from the name “e.”
For( i = 0, i < 10, i++, Show( i, e() ^ i ) );
Be careful that parentheses match. Every ( needs an ), or else errors result.
On Windows, the script editor can match fences (parentheses, brackets, and braces). Press CTRL-] with
your cursor in any part of a script. The editor searches for fences, highlighting the text between the first set
of opening and closing fences that it finds. Repeat this process to highlight the next-higher fence.
Names
A name is exactly what you think: something to call a thing. For example, when you assign the numeric
value 3 to a global variable in the statement
too. In the statement
Log( 4 ), the word “Log” is the name of the logarithm function. A name is any
language token that is not a number or a string or a special symbol operator (such as
a = 3, “a” is a name. Commands and functions have names,
+ or – or ++ or ^).
Names have a few rules:
•Names must start with an alphabetic character or underscore (
a-z A-Z _), and can continue with the
following:
– alphabetic characters (
– numeric digits (
a-z A-Z)
0-9)
– whitespace characters (spaces, tabs, and line and page delimiters)
– double-byte characters
– a few punctuation or special characters (apostrophes (
(
\), underscore (_))
‘), percent signs (%), periods (.), backslashes
•When comparing names, the whitespace characters (like spaces, tabs, and newlines) are ignored, and
upper and lower case is not distinguished. For example, the names
Forage and for age are equivalent.
Note: Why does the language allow whitespace characters inside names? For one reason, it is good for the
names of commands and options to match the equivalent commands in menus and windows. Another
reason is because people think in terms of multi-word names. The price of allowing whitespace characters is
that JSL needs more delimiters, specifically commas and parentheses.
•Actually, you can still have a name that is any other sequence of characters. If it does not obey the rules
above, it needs to be quoted and placed inside a special parser directive called
use a global variable with the name
-)(*$%(*&$%A, you must use Name( ) every time it appears in
is harmless when it is not needed. For example, foo and Name( "foo" ) are exactly the same
Name
thing.
Numbers
Numbers can be written as integers, decimal numbers, in scientific notation with an E preceding the power
of ten, and as dates, times, or date/time values. A single period by itself is the missing numeric value
(sometimes called NAN for “not a number”).
For example, these are all numbers:
. 1 12 1.234 3E3 0.314159265E+1 1E-20
If you precede a number with a minus sign, the minus sign is usually interpreted as a prefix operator, not
part of the number. You can follow a number immediately with an E followed by a power of ten you want to
scale the number by. For example 3E2 means 3 times 10 to the power 2, or 300. If you need a negative
exponent of ten in E notation, that minus sign is part of the number.
Dates and Times
JMP supports datetime values in a variety of common date/time notation formats. Datetime values are
stored and computed as a number of seconds since midnight, January 1, 1904. However, you can enter a
datetime value literally, using the format ddMonyyyy:hh:mm:ss.ddd. For example:
x = 14Feb2002:19:15:00;
Several shorter forms can also be used for datetime literals:
x = 14Feb2002:19:15;
x = 14Feb2002;
y = 19:15:00;
y = 19:15;
JMP has numerous operators for converting datetime values to strings in common notations, for example:
invitation = "Would you like to dine with me on " || Long Date( x ) || "?";
These and other datetime subjects are detailed in “Datetime Operators,” p. 46.
Quoted Strings
Strings are put in double quotation marks. Be careful to include the end quotation mark, or your string
includes unintended text until it finds the next double quotation mark.
How do you put a double quotation mark inside a quoted string? Inside quoted strings, you can use a special
escape sequence
script and look at the title of the window:
New Window( "For example,\!"Hello\!" is a quoted string",
);
"Would you like to dine with me on Thursday, February 14, 2002?“
\! (backslash-bang) to precede a code for special characters. For example, run the following
Text Box( Char( Repeat( "*", 70 ) ) )
Chapter 2JSL Building Blocks29
The JSL Language
Warning: The null character is dangerous to use, because it is normally treated as the end of the string.
Ta bl e 2 .2 Escape Sequences for Quoted Strings
\!b
\!t
\!r
\!n
\!N
\!f
\!0
\!\
\!"
a. On Macintosh, this is CR (carriage return character, hexadecimal ‘0D’). On
Windows, this is CR LF (carriage return followed by a linefeed, hexadecimal ‘0D0A’).
Sometimes, long passages require a lot of escaped characters. In these cases, use the notation
blank
tab
carriage return only
linefeed (newline) only
inserts line breaking characters appropriate for the host environment
formfeed (page break)
null character. (See warning.) Type the number zero, not the letter O.
backslash
double quotation mark
a
\[...]\ and
everything between the brackets does not need or support escape sequences. Here is an example where
\[...]\ is used inside a double-quoted string.
jslPhrase = "The JSL to do this is :\[
a = "hello";
b = a|| " world.";
show(b);
]\ and you use the Submit command to run it.";
Matrices
Matrices can be specified as signed numbers inside brackets, with values separated by blanks or other
whitespace characters, and rows separated by commas or semicolons. Brackets are also used to represent
subscripting, when brackets occur after another expression. You can represent an empty matrix of no rows
and no columns by
A = [1 2, 3 4];
two = A[1, 2]; // subscript picks the first row, second column element from A
Empty = [];
[].
Matrices are discussed at greater length in the “Matrices” chapter.
30JSL Building BlocksChapter 2
The JSL Language
Lists
Like matrices, lists are compound data structures, but they are more flexible than matrices. Lists are a way to
store numerous items of different type: numbers, text strings, expressions, matrices, and even other lists.
Lists can be expressed as arguments for the function
A = List( 1, 2, B, Sqrt( 3 ), List( a, b, 3 ) );
A = {1, 2, B, Sqrt( 3 ), {a, b, 3}};
List( ), or simply between { and } curly braces:
Lists are discussed at greater length under “Lists,” p. 68 in the “Programming Functions” chapter.
Associative Arrays
An associative array maps unique keys to values (possibly non-unique). Other languages call this type of data
structure a dictionary a map, a hash map, or a hash table. A key is a quoted string, while the value associated
with that key can be strings, numbers, dates, matrices, lists, and so forth. For example:
Associative arrays are discussed at greater length under “Associative Arrays,” p. 72 in the “Programming
Functions” chapter.
Operators
Operators are one- and two-character symbols for common arithmetic actions. Operators come in several
varieties: infix (with arguments on either side, such as
its right side, such as
incrementing a).
JSL operators all have function equivalents. Operators are discussed at greater length under “Operators,”
p. 33.
File Paths
In JMP, the preferred file path format is the POSIX (or UNIX) format, with forward slashes as separators.
Each host still accepts its native format for compatibility. This, along with path variables, often eliminates
the need for
Path variables are supported at the beginning of a POSIX path. JMP recognizes
SAMPLE_DATA, ENGLISH_SAMPLE_DATA, SAMPLE_IMPORT_DATA, SAMPLE_SCRIPTS, SAMPLE_IMAGES,
JMP_HOME, and TEMP as path variables. If you also have installed JMP Genomics, GENOMICS_HOME is also
available. They are used with a dollar sign at the beginning of a path.
Users can also add their own path variables, or override some of the built-in ones with the JSL functions
+ in 3+4, or = in a=7), prefix (with one argument on
!a for logical negation), or postfix (with one argument on its left side, such as a++ for
if(host is(...)...) logic to open files in a portable script.
HOME, DOCUMENTS,
Open("$SAMPLE_DATA/Big Class.jmp")
Chapter 2JSL Building Blocks31
The JSL Language
posixPath = Set Path Variable(varName, posixPath);
posixPath = Get Path Variable(varName);
varName
is case-sensitive and does not include the dollar sign.
Confusion alert! You cannot override HOME, DOCUMENTS, or TEMP, and Get Path Variable does not
retrieve the settings for them. Instead, use this JSL function:
posixPath = Convert File Path("$HOME");
There are JSL functions for accessing the default directory:
posixPath = Set Default Directory(posixPath);
// returns the new directory path
posixPath = Get Default Directory();
The default directory is used for resolving relative paths. The file search list is also used for resolving relative
paths for opening files (not for saving).
For the <optional> arguments above, the defaults are absolute, POSIX, and a base path of the default
directory. The input path can be in Windows or POSIX style.
Path variables have the following characteristics:
•When changing the language that JMP runs in, their definitions are changed to match the language
automatically.
•When changing from running one version of JMP to another (for example, JMP 8 and then JMP 9),
their definitions are changed to match the language automatically.
•The path variable
$ENGLISH_SAMPLE_DATA always holds the definition of the English Sample Data
folder.
The path variable
$ALL_HOME points to a folder that can be accessed by all users on a machine. These
folders are different according to the operating system:
Ta bl e 2 .3 $ALL_HOME Path Variable
Operating SystemAll Users Folder
Windows 7 or
C:\ProgramData\SAS\JMP\9
Windows Vista
Windows XPC:\Documents and Settings\All Users\Application Data\SAS\JMP\
Macintosh/Users/Shared/
32JSL Building BlocksChapter 2
The JSL Language
Comments
Comments are notations that you add to your code that are ignored by the parser. Comments can be started
by either
// or /*. The // form continues until the end of a line. The /* form continues until a closing */
. Comments cannot be inside quoted strings.
Ta bl e 2 .4 Comments in JSL Scripts
SymbolSyntaxExplanation
// // comment
/* *//* comment */
Note: Add
Data Elements
Generally the language tokens translate into JSL data elements and expressions. JSL uses the following basic
elements in the language:
•integers
•numbers (floating point)
•character strings
•names
•lists
a list holds a number of other values, including nested lists and expressions
Doe family = List( John Doe, Jane Doe, Baby Doe );
Doe family = { John Doe, Jane Doe, Baby Doe };
•associative arrays
an associative array maps keys to values, which can be just about any other data element
•matrices
a matrix is a row-by-column table of numbers
Design Matrix = [1 1, 1 -1];
•expressions
expressions can be treated as complex data and manipulated by certain operators
•references to scriptable objects:
Start a comment line; does not have to be at beginning of line, but
everything following to the end of the line is a comment.
A comment that can appear in the middle of a line of script. Script text
before and after the comment is undisturbed. The
/*...*/ punctuation
is a convenient way to remove portions of script temporarily. These two
statements are equivalent:
c=1+ /* comment */ 2;
c=1+2;
//! to the beginning of a script to prevent it from being seen by users of the script.
Chapter 2JSL Building Blocks33
The JSL Language
•data table columns
Operators
In order to make writing algebraic expressions natural, JSL has adopted certain special character operators.
These operators have the same meaning as if the phrase had been written as a message or function. For
example, the following two statements are equivalent:
Note: Usually white space is ignored in JSL, so that “netincomeaftertaxes” and “net income after taxes” are
the same thing. There is one exception: the two-character operators must not have a space between
characters, or they will be misunderstood. Always type these without spaces in between:
data table reference
obtained from the Open() or Current Data Table() function (represented
by dt in syntax summaries)
data column reference obtained from the Column() function (represented by col in syntax
summaries)
scriptable object reference obtained from platform launches or Scriptable class subscripting
(represented by obj in syntax summaries)
displayBox reference reports or parts of reports in windows (represented by db in syntax summaries)
Net Income After Taxes = Net Income - Taxes;
Assign( Net Income After Taxes, Subtract( Net Income, Taxes ) );
The assignment operation can be written either as a function Assign or as an infix operator =. Similarly,
subtraction can be done with the
Subtract function, or the infix minus sign; they are equivalent inside
JMP.
Another common operator is the semicolon (
; ). The semicolon is a gluing operator that is used to both
separate yet join one expression to another in a programming sequence. The function equivalent of this is
Glue, so a;b is the same as Glue(a,b). The semicolon or Glue operator returns the result of its last
argument. It is also legal to end an expression with a semicolon. This might lead you to think of it as a
statement terminator like some other languages, but it is designed as an infix operator. Terminating
semicolons are allowed at the end of a script stream and before a closing parenthesis or closing brace:
) or }.
Table 2.5 shows operators and their function equivalents. The operators are grouped in their order of
precedence, where the binding priority decreases with each group. For example, in
multiplication
Ta bl e 2 .5 Operators and Function Equivalents In Precedence Order
OperatorSyntaxExplanation
{}List{a,b}
a*b is done before the addition of c.
Construct a list.
List(a,b)
a*b+c, the
34JSL Building BlocksChapter 2
The JSL Language
Ta bl e 2 .5 Operators and Function Equivalents In Precedence Order (Continued)
OperatorSyntaxExplanation
[]Subscripta[b,c]
Subscript(a,b,c)
++Post Incrementa++
Post Increment(a)
––Post Decrementa––
Post Decrement(a)
^Powera^b
Power(a,b)
Power(x)
–Minus–a
Minus(a)
!Not!a
Not(a)
*Multiplya*b
Multiply(a,b)
:*EMulta:*b
EMult(a,b)
Subscripts identify specific elements within a
data element a, where a could be a list, a matrix,
a data column, a platform object, a display box,
and so forth.
Adds one (1) to a, in place.
Subtracts one (1) from a, in place.
Raise a to exponent power b. With only one
argument, 2 is assumed as the power, so
Power(x) computes x
2
.
Reverses sign of a.
Maps nonzero values to 0, maps 0 values to 1.
Multiplies a by b.
Elementwise multiplication for matrices a and b.
/Dividea/b
Divide(a,b)
Divide(x)
:/EDiva:/b
EDiv(a,b)
+Adda+b
Add(a,b)
–Subtracta–b
Subtract(a,b)
||Concata||b
Concat(a,b)
Divide(a, b) divides a by b.
Divide(x) interprets the argument as a
denominator and implies 1 as the numerator,
yielding the reciprocal 1/x.
Elementwise division for matrices a and b.
Adds a and b.
Subtracts b from a.
Concatenates strings together.
Chapter 2JSL Building Blocks35
The JSL Language
Ta bl e 2 .5 Operators and Function Equivalents In Precedence Order (Continued)
OperatorSyntaxExplanation
matrix1 || matrix2
Concat(matrix1, matrix2)
|/VConcatmatrix1|/matrix2
VConcat(matrix1, matrix2)
::Indexa::b
Index(a,b)
<<SendSend(object, message)
object << message
==Equala==b
Equal(a,b)...
!=Not Equala!=b
Not Equal(a,b)...
<Lessa<b
Less(a,b)...
<=Less or Equala<=b
Less or Equal(a,b)
Horizontally concatenate matrices.
Vertically concatenate matrices.
For matrices, generates the integers from a to b.
(Colons are also used as infix operators for
scoping, where
and
::a means JSL global variable a. See
:a means data table column a,
“Global Scoping Operator,” p. 40.)
Send message to object.
Boolean values for comparisons. They all return
1 if true, 0 if false. Missing values in either a or b
causes a return value of missing, which evaluates
as neither true nor false.
>Greatera>b
Greater(a,b)
>=Greater or Equala>=b
Greater or Equal(a,b)
<=, <Less Equal Lessa<=b<c
Less Equal Less(a,b,c)
<, <=Less Less Equala<b<=c
Less Less Equal(a,b,c)
&Anda&b
And(a,b)
Range check. Return 1 if true, 0 if false. Missing
values in either a or b propagate missing values.
Logical And. Returns true if both are true. See
“Missing Values,” p. 82 in the “Programming
Functions” chapter, for treatment of missing
values.
36JSL Building BlocksChapter 2
Context: Meaning is Local
Ta bl e 2 .5 Operators and Function Equivalents In Precedence Order (Continued)
OperatorSyntaxExplanation
|Ora|b
Or(a,b)
=Assigna=b
Assign(a,b)
+=Add Toa+=b
AddTo(a,b)
–=Subtract Toa–=b
SubtractTo(a,b)
*=Multiply Toa*=b
MultiplyTo(a,b)
/=Divide Toa/=b
DivideTo(a,b)
;Gluea;b
Glue(expr, expr, ...)
Context: Meaning is Local
Logical Or. Returns true if either or both are
true. See “Missing Values,” p. 82 in the
“Programming Functions” chapter, for
treatment of missing values.
Put the value of b into a. Replaces the current
value of a.
Add the value of b into a.
Subtract b from a, and put back into a.
Multiply b with a, and put back into a.
Divide b into a, and put back into a.
First do a, and then do b.
The JSL language is used both for scripting and programming. Programming emphasizes results, which
build from the inside out. Scripting emphasizes context, which builds from the outside in. Understanding
this distinction is crucial to understanding how JMP executes a script. For producing more complex JSL
programs, we recommend that you use namespaces, as described in “Advanced Scoping and Namespaces,”
p. 390 in the “Advanced Concepts” chapter.
Programming Versus Scripting
For example, consider how a typical programming statement evaluates:
x = Log( a * b ^ (c + d) )
The goal of this program is to find a result to assign to x. According to the rules of precedence for arithmetic
operators, this starts on the inside by evaluating c and d and adding them together. Next b is evaluated and
then raised to that power (), and that result in turn is multiplied by the evaluation of a. That result is
next passed to the
Log function, which finds the logarithm, and finally that result is assigned to x.
Evaluation started on the inside with
Now consider a typical scripting statement:
cd+
c + d and worked its way out.
Chapter 2JSL Building Blocks37
Context: Meaning is Local
Fit Model( Effects( a, b, a * b ), Y( c ), Run Model );
The goal of this script is to launch an analysis platform and return a report. Evaluation starts on the outside
with
Fit Model, which calls the platform for fitting models. This platform in turn knows that Effects is
specifying the independent terms of a model, and in that context, the phrase
meaning. In the
Log statement above, it meant to multiply. In the Fit Model statement, a*b means the
a*b takes on a whole new
interaction term of a and b. In turn, a and b are evaluated as the data columns assigned to the global
variables a and b. The platform also knows that
term. Finally the platform sees
Model
and worked its way in.
Run Model and goes to work. Evaluation started on the outside with Fit
Y means that the column assigned to c is to be the response
Data Table Context
A formula column is evaluated down the rows of the data table. If a script needs to refer to a specific cell
each time, then you give a subscript to a specific row number. For example, this formula column gives the
ratio within each row, where
New Column( "Ratio", formula( Height / Weight ) );
This gives the ratio of each row’s Height to the Weight in row 1:
New Column( "Ratio B", formula( Height / Weight[1] ) );
There is a current row number that determines the cells of the data table, which can be set or displayed with
the function
Row(), for example.
height and weight are columns such as in the sample data table Big Class:
Row(); // returns current row number
Row() = 3; // makes the third row the current row
By default, the current row is always 0, which means that the following statement on its own returns a
missing value and be generally useless.
ratio = height / weight;
However, if you include something in the script to set the current row to a specific row number (for
example, the third), the result is assigned to the global variable ratio.
Row() = 3;
ratio = height / weight;
Another possibility is to ignore the current row and instead use subscripts to ask for a specific row number.
This version divides the height in row 3 by the weight in row 4:
::ratio = height[3] / weight[4]
Still another possibility is to create a column ratio and iterate the division a row at a time down the whole
column:
New Column( "ratio" );
For Each Row( :ratio = height / weight );
If you are working with global variables, pre-evaluated statistics, and so forth, you do not need to consider
the current row. (Pre-evaluated statistics are single number values computed from the data table, as discussed
in “Pre-Evaluated Statistics,” p. 151 in the “Data Tables” chapter.)
38JSL Building BlocksChapter 2
Context: Meaning is Local
::myCalc = Col Mean( height ) / Col Mean( weight );
Scoping Operators
The scripts in the previous section used colons : or double colons :: in front of some names. These are scoping operators. They tell JMP how to interpret the names that follow in cases that could be ambiguous.
For example, when a data table column and a JSL global variable have the same name. Scoping operators
and the rules for name resolution are discussed in detail under “Name Resolution,” p. 38, later in this
chapter.
:x; // data table column
::x; // JSL global variable
x; // depends on state when first used
Name Resolution
The following types of objects can be identified by name:
•Columns and table variables in a data table
•Global variables, which exist for a session
•Scriptable object types
•Parameters and
Locals inside formulas
If a name is just part of a script for an object, then its meaning is usually the name of an option or method
in the object. Otherwise it is considered by the evaluator using the rules in this section. If the name is
followed by parentheses, then it is regarded as a function. Otherwise, the name is looked up as some object.
Global variables are names that exist for the remainder of a session to hold values. Globals can contain many
types of values, including numbers, strings, lists, and references to objects. They are called globals because
they can be referred to almost anywhere, not just in some specific context.
Most of the time, you can just use an object’s name directly to refer to the object.
Ratio = Height / Weight;
N = N + 1;
Distribution( ... );
Now the trick is to learn the rules as to when you are referring to a column, when to a global, and when to a
type. This knowledge helps you to know when you can use the name directly and when you need to qualify
it somehow.
Name-Binding Rules
From a programming point of view, name resolution is important when getting and setting values in a
script. Names that are referred to for name-reference, rather than to get or set a value, are not resolved.
Rather they are just passed along, as with a script to launch a platform specifying certain columns to be
analyzed.
There are six possible resolutions for any name in a script. JMP tries each of the following in order:
Chapter 2JSL Building Blocks39
Context: Meaning is Local
1. If followed by a pair of parentheses ( ), look it up as a function; see “Function Resolution Rules,” p. 42,
for details.
2. If not prefixed by
3. If not prefixed by
:, look it up as a global variable.
::, look it up as a data table column or table variable.
4. Look it up as a local variable.
5. Look it up as a platform launch name (for example,
Distribution or Bivariate).
6. If used as the target of an assignment (as an L-value), create and use a global variable.
A name in a script is resolved the first time it is used to get or set a value, and its resolution persists
thereafter. The operators
: and :: are always resolved respectively as As Column() and As Global().
Exceptions
If a name is resolved to a column in a data table that is closed, then it re-resolves the next time it gets or sets
in case the data table has been opened in the meantime. Other exceptions are function definitions, column
formulas, and nonlinear formulas.
When an Unscoped Name Refers to a Table Column
When an unscoped name is resolved to get or set a value, then it refers to a column in a data table, rather
than a global variable under these circumstances:
•if no global, local, or parameter of that name already exists,
•and the data table in context has a column of that name,
•and
– either the current row is set to a positive value
Warning: The current default row is now 0 instead of 1, as in JMP 3 and earlier.
– or the name is subscripted. For example,
If the data table has a table variable by that name, then the table variable takes precedence. In all other cases,
it binds to a global, local, or parameter.
Note: When an unqualified name in JSL is resolved to a data column in a data table, it must be associated
with the current data table. This is different from the rule in JMP 4 and earlier.
Exceptions
Column formulas and nonlinear formulas.
Column Scoping Operators
Column scoping operators can be used to force names to be resolved as columns.
A[i].
40JSL Building BlocksChapter 2
Context: Meaning is Local
1. The prefix colon ( : ) means that the name refers to a table column or table variable only, never a global.
The prefix
Current Data Table() either returns or is assigned.
:colName
: refers to the current data table context. The current data table is the data table that
2. The infix colon ( : ) operator extends this notion to specify which data table has the column by using a
data table reference (data table references are discussed in the chapter “Data Tables,” p. 85). The
function equivalent is
dataTableRef:name;
As Column(dataTableRef, name);
As Column.
Therefore, these are equivalent:
:name;
Current Data Table():name;
As Column( Current Data Table(), name );
The Column function can also be used. However, it always evaluates its arguments, so you need to specify a
row to refer to a cell rather than the whole column.
Column( "X" ); // Refers to column X.
Column( "X", 12 ); // Refers to the cell of row 12, column X.
Column( "X" )[]; // Refers to the cell of the current row of column X.
Column( a ); // Evaluates a and looks up the column of the result.
Global Scoping Operator
A global scoping operator can be used to force names to be resolved as globals. The prefix double-colon
(
:: ) means that the name refers to a global only, never a table column. The function equivalent is As
Global
Ta bl e 2 .6 Scoping operators
.
::globalName;
As Global( globalName );
Operator and
Function
:As Column:name
::As Global::name
SyntaxExplanation
Scoping operator. Forces name to be evaluated as a data table
dt:name
As Column(dt,
name)
column in the table given by the optional data table reference
argument, dt, rather than as a global variable.
Scoping operator. Forces name to be evaluated as a global
As Global(name)
variable, not a data table column.
(Notice that double-colon is also used as an infix operator to
represent ranges.)
Chapter 2JSL Building Blocks41
Context: Meaning is Local
Frequently-Asked Questions
Should you scope?
Yes. When in doubt, scope. Scoping is especially important if you are writing scripts that define globals with
the same names as data table columns that you are not aware of. For example, scripts that might be used by
many people on a variety of data tables. Since global names always take precedence, you have to work to
ensure that the column name references map to a column and that globals do not map to a column. If you
are writing such scripts, consider using explicit scoping and namespaces. See “Advanced Scoping and
Namespaces,” p. 390 in the “Advanced Concepts” chapter.
Prefix scope operators do not take run-time overhead after the first resolution. Infix scope operators always
take run-time overhead.
What is the difference between a column referred to by name, and a column reference? If I have a column
reference in a global, how do I assign a value to a cell in the column?
Try submitting the following examples one line at a time. These scripts assume that you have a data table
with a column named “A” and you do not have a global variable named “A.” The first few examples begin
with a
Row()=3 assignment to set the current row to a valid row, in this case the third row. The current row
is irrelevant in the last few examples.
// assumes a data table with a column "A" and sufficient rows
Row() = 3; A = 1; //sets the current row of A to 1
Row() = 3; :A = 2; //sets the current row of A to 2
Row() = 3; :"A" = 3; //sets the current row of A to 3
ColA = Column( "A" ); //sets the global ColA to refer to column A
ColA[3] = 4; //sets the third row of A to 4
ColA << Formula( 6 ); //sets the formula for A to be 6
Confusion alert! The current row for scripting is not related to rows being selected
(highlighted) in the data table or to the current cursor position in the data table
window. The current row for scripting is defined to be zero (no row) by default. You
can set a current row with
setting only lasts for the duration of that script. Then,
Row (for example, Row() = 3). Please note that such a
Row() reverts to its default
value, zero. This behavior means that submitting a script all at once can produce
different results than submitting a script a few lines at a time.
Another way to establish a current row for a script is to enclose it in
For Each Row,
which executes the script once for each row of the current data table. See “What is the
Current Row?,” p. 101 in the “Data Tables” chapter, for more information.
Will a scoping operator “stick” to its name?
Yes. Once you use a scoping operator with a name, that name continues to be resolved accordingly for all
subsequent occurrences of the name. For example, to protect against overwriting data tables that happen to
contain a column named “i” when you use i as an index inside a
For() loop, declaring ::i at the head of
the script is all the protection that you need for the whole script.
::i = 1;
42JSL Building BlocksChapter 2
Gluing Expressions Together
For( i = 1, i < 10, i++, doScript );
Normally this is not a problem since at time of execution Row() would typically be 0. However, if Row() is
greater than 0, such as inside a
::i = 1;
For Each Row( For( i = 1, i < 10, i++, doScript ) );
For Each Row() loop, you should be careful:
Which has precedence when scoping, ":" or "[ ]"?
Scoping occurs before subscripting. This means that these two lines of code are equivalent:
dataTable:colName[i]
(dataTable:colName)[i]
Function Resolution Rules
A name followed by a list of arguments enclosed in parentheses is the syntax for a number of contexts in
JSL:
•a call to a built-in function
•a call to a user-defined function
•a named argument
•a nesting in a script for an object: either an option with an argument, or a sub-object with messages, or
any other use recognized by the object itself
Gluing Expressions Together
The semicolon operator evaluates each argument in succession, returning the result of the last one. For
example:
i=0; j=2
The semicolon in other languages is used as a statement terminator character. In JSL it is just a binary
operator for gluing together expressions. The result returned is the result of the right-most expression. The
function version of the semicolon is
Glue(a=2,b=3)
a=2; b=3
You can also add a semicolon at the end of an expression as a terminator character, but it is not required.
The semicolon is ignored if nothing follows it. Trailing semicolons are allowed at the end of a script stream,
and before a closing parenthesis or closing brace:
semicolon to avoid errors when copying and pasting small scripts into larger ones.
The
First function works just like Glue ( ; ) except that it returns the first argument’s result instead of the
last’s. For example, this script increments a counter global i after getting the i
enclosing the two steps inside
counter.
Glue, which makes the following two statements the same:
First( ) enables the script to return the datum, not the new value of the
) or }. It is useful to get in the habit of using a final
th
value of a variable, but
Chapter 2JSL Building Blocks43
Variables
i=1; First(height[i], i++);
Example
What are the results of this script?
a=root(b=9;4);
Semicolon has weak precedence, so when JMP evaluates this statement, it first attempts to evaluate the
quantity inside the parentheses. JMP simply executes two separate statements:
b=9;
4;
Thus it assigns 9 to b, then it evaluates the last statement, 4. Several statements glued together return the
return value of the last statement, so 4 is returned for the expression inside the parentheses. JMP then takes
the square root of 4 and assigns the result (2) to a. Assignment always returns the assigned value, so the
ultimate return value for the whole script is 2. So, this script results in two assignments,
a=2 and b=9, and
returns 2.
What are the results of this script?
a=root(First(b=9,4));
executes both its statements but returns the result of the first, not the last. So the statement 4
First
accomplishes nothing, 9 is assigned to b, and the square root of 9, 3, is assigned to a.
Variables
Assigning a variable this way:
x=2;
makes a global variable. JMP has a single global variable space that all scripts use. You can also create local
variables.
We recommend that you begin each script with
variables local to your script, instead of using the global space. This strategy ensures that scripts cannot
“collide” by accidentally using the same global variable names and over-writing their values.
If you turn the
variable accessible throughout your script, but does not affect the global variable space.
The following commands can help you manage variables.
Watch
Watch lets you keep track of the value in a variable.
Watch draws a window to report the values of variables you list. Use the named argument All to watch the
values for all variables. The window updates whenever values change while the script is executing, or you can
Names Default To Here(1). This mode makes all your
Names Default To Here mode on, then assigning a variable as shown above makes that
44JSL Building BlocksChapter 2
Variables
manually change values yourself by simply editing the value shown in the Watch window. This is a useful
debugging tool.
Watch(a, b);
Watch(all);
Show Symbols, Clear Symbols, and Delete Symbols
Show Symbols() lists all variables and namespaces that are defined both globally and in the local script,
along with their current values.
globally and in the local script.
Note: The older Show Globals() and Clear Globals() functions are aliases of the newer Show
Symbols() and Clear Symbols() functions.
Clear Symbols erases the values set for variables that are defined both
The function
Globals()
c = "Global Variable"; // this is in the global space
Names Default To Here( 1 );
a = 5; // this is local to this script
b = 6; // this is local to this script
Show Symbols();
Clear Symbols();
Show Symbols();
Delete Symbols() actually removes all global variables and namespaces, while Clear
removes only their values.
// Locals
a = 5;
b = 6;
// 2 Locals
// Globals
c = "Global Variable";
// 1 Globals
// Locals
a = Empty;
b = Empty;
// 2 Locals
// Globals
c = Empty;
// 1 Globals
Delete Symbols();
Show Symbols();
Nothing is displayed in the log after the last Show Symbols(), because they have all been completely
removed from memory.
Chapter 2JSL Building Blocks45
Variables
Note: None of these three functions affect namespaces, although they do affect variables that hold
references to namespaces. To show namespaces, use
<< Delete.
Show Namespaces(). To delete a namespace, use ns
Locking and Unlocking Symbols
If you want to lock a symbol to prevent it from being changed, use Lock Symbols(). (Lock Globals()
is an alias.)
Lock Symbols (name1, name2, ...)
To release the lock and enable the global to be changed, use Unlock Symbols(). (Unlock Globals() is
an alias.)
Unlock Symbols (name1, name2, ...)
The primary use of these two commands is to prevent inadvertent changes to variables. For example,
locking a variable prevents a
another script.
Note: You c a nn ot us e Lock Symbols() to lock a namespace. Instead, use ns << Lock().
Clear Symbols() command from clearing a variable that is being used by
Local
Local lets you deal with local variables without affecting the name space around you. For example, suppose
you want to call something x, but there could already be an x global in another script that is calling your
script. Just put x inside a
Local block. This differs from using Names To Default To Here(1)
because you can set portions of a script local, thus insulating a portion from the rest of the script.
y= Local({x},
x = sqrt(b^2-4*a*c);
{(-b+x)/(2*a), (-b-x)/(2*a)});
The general form is:
Local( {list_of_variables_or_assignments}, body );
All occurrences of names in the body expression that match names listed for the first argument are resolved
locally.
Locals can be nested in Functions and other Locals.
Another example: in the following expression, mn and mx are never seen outside the scope of the
Local
function:
y = local( {mn=min(x,y),mx=max(x,y)}, mx*(mx-1)+mn );
This example manipulates an expression temporarily without changing the permanent contents of the
expression:
polynomial = Expr( a * x ^ 2 + b * x + c );
Show( polynomial );
polynomial = a * x ^ 2 + b * x + c;
46JSL Building BlocksChapter 2
Datetime Operators
Local( {polynomial = Insert( Name Expr( polynomial ), Expr( d * x ^ 3 ), 1 )},
Show( polynomial )
);
polynomial = d * x ^ 3 + a * x ^ 2 + b * x + c;
Show( polynomial );
polynomial = a * x ^ 2 + b * x + c;
Datetime Operators
Constructing Dates
You can construct dates with the following operators. If it were the stroke of midnight, 1 December 2003,
all of the following statements would be equivalent. Each would return 3153081600, and you could pass
any of them to a date notation operator such as
Date DMY(1,12,2003);
Date MDY(12,1,2003);
Today();
3153081600
Long Date to get a recognizable format:
long date(today());
"Monday, December 1, 2003"
These operators are handy if you are setting up a date column to label rows, or any other case where you can
describe a series of date values generally:
new column("Entry date", format("m/d/y"),formula(Date DMY(row(),3,2001)));
// be sure the format is available on your machine
Extracting Parts of Dates
You can extract parts of date values using the operators Month, Day, Year, Day Of Week, Day Of Year,
Week Of Year, and Time Of Day, which all return integers. For example:
day of year(today());
335
Chapter 2JSL Building Blocks47
Datetime Operators
Confusion alert! Because Sunday is the first day of the week, the first Sunday of each year always
starts week 2. Days before the first Sunday (if there are any) are in week 1. This means that in a
year in which January 1 is on Sunday, the first week is counted as the second week.
Example:
Week of Year(Date DMY(1,1,2006));
2
In years in which Sunday is the first day of the year, subtract 1 from Week Of Year() to obtain
the correct week number.
Arithmetic on Dates
You can perform the usual arithmetic operations with date/time data as with any other numeric data. For
example, you could find the days elapsed between entries:
new column("Days elapsed",
formula(
if(row()==1,., //to avoid error for row 1
//else for rows after 1:
(:Entry date[row()]-:Entry date[row()-1])/in days())));
Converting Datetime Units
The In Minutes, In Hours, In Days, In Weeks, and In Years operators are useful for re-expressing a
time interval in units other than seconds. For example, this returns the number of fortnights between now
and the next Leap Day.
(Date DMY(29,2,2004)-Today())/InWeeks(2);
Usually n is 1, but you could use In Years(10) (for example, to re-express an interval in decades).
Y2K-Ready Date Handling
JMP uses its own Y2K-ready algorithms for interpreting and displaying date/time strings rather than
supporting operating system-specific date/time formats. JMP respects the date/time separator-characters
chosen in the Regional Settings control panel (Windows) or the Date&Time control panel (Macintosh) for
interpreting and displaying dates.
JMP always displays four-digit years regardless of Regional Settings. If for some reason it should be necessary
to show two-digit years, use JMP’s operators for manipulating character strings.
Two-digit years are interpreted according to the current system clock year, according to the rules below. To
avoid ambiguity or override the default interpretation, type a four-digit year value.
48JSL Building BlocksChapter 2
Datetime Operators
Ta bl e 2 .7 How JMP interprets two-digit years
What you
type
00–10before 1990 (Win)19__type 5 in year 19791905
11–89 (Win)any timecurrent centurytype 13 in year 19881913
11–90 (Mac)type 13 in year 20242013
90–99 (Win)before 201119__ type 99 in year 19991999
91–99 (Mac)during or after 201120__type 99 in year 20152099
Note that three locale-specific formats (Locale Date, Locale Date Time h:m, Locale Date Time h:m:s) always
display the date time according to your regional settings.
Datetime Notation
Several operators convert numbers directly to common formats.
Short Date(2998080000);
"01/02/1999"
Long Date(2998080000);
"Saturday, January 2, 1999"
Abbrev Date(2998080000);
"Jan 2, 1999"
mdyhms(2998080000);
"01/02/1999 12:00:00 AM"
You can also use the Format and InFormat operators for displaying and entering date/time values in one of
many notation formats.
When it is evaluatedResultExamplesResult
before or during 1990 (Mac)
during or after 1990 (Win)20__type 5 in year 19912005
after 1990 (Mac)
Format(3096558900,":day:hr:m");
":35839:19:15"
InFormat("02Jan1999 13:01:55","ddMonyyyy h:m:s");
02Jan1999:13:01:55
Dates that are the results of expressions that are to be displayed in a text window (like the log window) are
given as a date attribute using
x = As Date(8Dec2000 + inDays(2));
As Date. For example:
shows as
10Dec2000
Chapter 2JSL Building Blocks49
Datetime Operators
The formats JMP currently supports are shown in Table 2.8. You can also use them for the format argument
to a
Format message to a data column, as discussed in “Display Formats,” p. 127 in the “Data Tables”
chapter. Note that the date-separator character on your machine might differ from the
/ character shown
here.
You c a n enter time values in 24-hour format (military time) or with AM/PM designators.
Ta bl e 2 .8 Date/time formats supported in JMP
TypeFormat stringExample
Date only"m/d/y""01/02/1999"
"mmddyyyy""01021999"
"m/y""01/1999"
"d/m/y""02/01/1999"
"ddmmyyyy""02011999"
"ddMonyyyy""02Jan1999"
"Monddyyyy""Jan021999"
"y/m/d""1999/01/02"
"yyyymmdd""19990102"
“yyyy-mm-dd”“1999-01-02“
“yyyyQq“1999Q1
Date and time"m/d/y h:m""01/02/1999 13:01"
"01/02/1999 1:01 PM"
"m/d/y h:m:s""01/02/1999 13:01:55"
"01/02/1999 1:01:55 PM"
"d/m/y h:m""02/01/1999 13:01"
"02/01/1999 1:01 PM"
"d/m/y h:m:s""02/01/1999 13:01:55"
"02/01/1999 1:01:55 PM"
“y/m/d h:m”‘1999/01/02 13:01’
‘1999/01/02 1:01 PM’
“y/m/d h:m:s”‘1999/01/02 13:01:02
‘1999/01/02 1:01:02 PM’
"ddMonyyyy h:m""02Jan1999 13:01"
"02Jan1999 1:01 PM"
50JSL Building BlocksChapter 2
Datetime Operators
Ta bl e 2 .8 Date/time formats supported in JMP (Continued)
TypeFormat stringExample
"ddMonyyyy h:m:s""02Jan1999 13:01:02"
"02Jan1999 1:01:02 PM"
"ddMonyyyy:h:m""02Jan1999:13:01"
"02Jan1999:1:01 PM"
"ddMonyyyy:h:m:s""02Jan1999:13:01:02"
"02Jan1999:1:01:02 PM"
"Monddyyyy h:m""Jan021999 13:01"
"Jan021999 1:01 PM"
"Monddyyyy h:m:s""Jan021999 13:01:02"
"Jan021999 1:01:02 PM"
Day number and
time
Duration“:day:hr:m““52:03:01”, which reads fifty-two days, three hours, and
":day:hr:m""34700:13:01"
":33:001:01 PM"
":day:hr:m:s""34700:13:01:02"
":33:001:01:02 PM"
"h:m:s""13:01:02"
"01:01:02 PM"
“h:m”"13:01"
"01:02 PM"
“yyyy-mm-ddThh:mm”1999-01-02T13:01
“yyyy-mm-ddThh:mm:ss”1999-01-02T13:01:02
one minute.
“:day:hr:m:s““52:03:01:30”, which reads fifty-two days, three hours, one
minute, and thirty seconds.
“hr:m““17:37”, which reads seventeen hours and thirty-seven
minutes.
“hr:m:s““17:37:04”, which reads seventeen hours, thirty-seven
minutes, and 4 seconds.
“min:s”“37:04”, which reads thirty-seven minutes and 4 seconds.
Long date"Date Long"(Display only) "Saturday, January 2, 1999"
Ta bl e 2 .8 Date/time formats supported in JMP (Continued)
TypeFormat stringExample
Locale Date“Locale Date”(Display only) Depends on the locale setting for your
operating system. For the United States, “01/02/1999"
Locale Date Time“Locale Date Time h:m”(Display only) Depends on the locale setting for your
operating system. For the United States, “01/02/1999
13:01“ or “01/02/1999 01:01 PM“
“Locale Date Time h:m:s”(Display only) Depends on the locale setting for your
operating system. For the United States, “01/02/1999
13:01:02“ or “01/02/1999 01:01:02 PM“
Note that the last five date/time formats are not available for date input.
Ta bl e 2 .9 Date/time operators
OperatorExplanation
In Minutes(n)
In Hours(n)
In Days(n)
In Weeks(n)
In Years(n)
Date DMY(day, month, year)
Date MDY(month, day, year)
Toda y( )
Second(datetime)
Minute(datetime)
These operators return the number of seconds per n minutes, hours, days,
weeks, or years. Divide by these to re-express an interval in seconds as an
interval in other units.
Returns the specified date, expressed as the number of seconds since
midnight, 1 January 1904. For example, the second Leap Day of the
second millennium is
DateDMY(29,2,2004), which returns
3160857600.
Returns the specified date, expressed as the number of seconds since
midnight, 1 January 1904. For example, the second Leap Day of the
second millennium is
DateMDY(2,29,2004), which returns
3160857600.
Returns the current date and time expressed as the number of seconds
since midnight, 1 January 1904. No arguments are accepted, but the
parentheses are still needed.
Returns an integer representation for the second part of the date-time
value supplied.
Returns an integer representation for the minute part of the date-time
value supplied.
52JSL Building BlocksChapter 2
Datetime Operators
Ta bl e 2 .9 Date/time operators (Continued)
OperatorExplanation
Hour(datetime)
Day(date)
Month(date)
Year(date)
Day Of Week(date)
Day Of Year(date)
Week Of Year(date)
Time Of Day(date)
Short Date(date)
Long Date(date)
Returns an integer representation for the hour part of the date-time value
supplied.
Returns an integer representation for the day of the month of the date
supplied.
Returns an integer representation for the month of the date supplied.
Returns an integer representation for the year of the date supplied.
Returns an integer representation for the day of the week of the date
supplied. Weeks are Sunday–Saturday.
Returns an integer representation for the day of the year of the date
supplied.
Returns an integer representation for the week of the year of the date
supplied. Weeks are Sunday–Saturday. Note that the first Sunday of the
year begins week 2.
Returns an integer representation for the time of day of the date/time
supplied.
Returns a string representation for the date supplied, in the format mm/
dd/yy. For example,
"02/29/04".
Returns a string representation for the date supplied, formatted like
"Sunday, February 29, 2004".
Abbrev Date(date)
MDYHMS(date)
Format(date, "format")
In Format(string, "format")
Parse Date(string, "format")
As Date(expression)
Returns a string representation for the date supplied, formatted like "Feb
29, 2004"
.
Returns a string representation for the date supplied, formatted like "2/
29/04 00:02:20"
.
Returns the value in the format specified in the second argument. Most
typically used for formatting date/time values from a number of seconds
to a formatted date. Format choices are those shown in the
Column Info
dialog box; also see Table 2.8 “Date/time formats supported in JMP,”
p. 49.
Parses a string of a given format and returns date/time value expressed as if
surrounded by As Date(), returning the date in
ddMonyyyy format.
Formats a number or expression so that it shows as a date when streamed
out to a text window.
Chapter 2JSL Building Blocks53
Currency
Currency
JMP supports the use of currency symbols. To set a specific currency, use the Format() function. The
syntax is:
Format(x,"format", <"currency code">, <decimal>)
where x is a column, or a number. (For datetime formats, see “Datetime Operators,” p. 46).
To designate a number or a column as a currency, the format argument must be set to “Currency”. Then
add the ISO 4217 code for a specific currency as a quoted string. This third argument is invalid unless the
format is set to “Currency”. For example:
Format(12345.6, "Currency", "GBP", 3)
"£12,345.600"
Inquiry Functions
How can you tell what type of data element you have? JSL has inquiry operators to test whether something
is or is not a specific type of data element.
JSL also has an inquiry operator to test whether a global variable, a data table, or a data column has a value
assigned or not:
assigned a value yet. Programmers call this an “uninitialized variable.” To check whether a global variable,
data table, or data column has a value yet, use
Is Empty. You can get errors if you try to refer to something that has not been created or
Is Empty with the name of the item.
Is Empty(myGlobal);
Is Empty(dt);
Is Empty(col);
In addition, JSL provides a general Type function that returns a string naming the type of the resulting
value. The possible type names are
that the previous results are scriptable and only continue with a script after
is especially useful when parts of a script depend on previous-generated results. Test
IsScriptable() returns true.
54JSL Building BlocksChapter 2
Inquiry Functions
Ta bl e 2 .1 0 Inquiry functions to identify object types
SyntaxExplanation
Is Number(x)
Returns 1 if the evaluated argument is a number or missing numeric value, or 0
otherwise.
Is String(x)
Is Matrix(x)
Is Expr(x)
Is Name(x)
Is List(x)
Is Associative Array(x)
Is Scriptable(x)
Is Empty(global)
Is Empty(dt)
Is Empty(col)
Type (x)
Returns 1 if the evaluated argument is a string, or 0 otherwise.
Returns 1 if the evaluated argument is a matrix, or 0 otherwise.
Returns 1 if the evaluated argument is an expression, or 0 otherwise.
Returns 1 if the evaluated argument is a name-only expression, or 0 otherwise.
Returns 1 if the evaluated argument is a list, or 0 otherwise.
Returns 1 if the evaluated argument is an associative array, or 0 otherwise.
Returns 1 if the evaluated argument is a scriptable object, or 0 otherwise.
Returns 1 if the global variable, data table, or data column does not have a value
(is uninitialized), or 0 otherwise.
Returns a string naming the type of X.
Version and Host Information
Host Is is an inquiry operator. Host Is returns a Boolean result, either 1 if true or 0 if false. This is useful
for identifying the current operating system in scripts intended for use on Windows and Macintosh
platforms. Although now not necessary,
Host Is was frequently used to open data tables. For example:
dt=if(
host is(Windows),
open("..\sample data\Big Class.JMP"),
host is(Macintosh),
open("::sample data:big class"));
Another use is to specify different text sizes in reports for different operating systems. If you commonly
write your scripts on Windows and share them with people who use them on Macintosh, the results can
look different from what you intended. For example, this line sets the text to a larger size on Macintosh and
a smaller size on Windows:
txtsize = if(host is(Mac),12,10);
The JMP Version() function returns the JMP version as a string. The function puts a leading blank on
the version if it is less than 10 to make it easier to compare versions 7, 8, or 9 with version 10 in the future.
This function is not available in releases before 6.0.
JMP Version();
" 9.0"
Chapter 2JSL Building Blocks55
Functions that communicate with users
Functions that communicate with users
Show, Print, and Write put messages in the log window. Speak, Caption, Beep, and StatusMsg
provide ways to say something to a viewer.
JMP’s scripting language has methods for constructing dialog boxes to ask for data column choices and
other types of information. See “Modal Windows,” p. 218 in the “Display Trees” chapter.
Writing to the log
Show
Show displays the items that you specify in the log. Notice that when you show variables, the resulting
message is the variable name, a colon
X=1;A="Hello, World";
show(X,A,"foo");
x = 1
a = "Hello, World"
"foo"
Print
Mail can send an e-mail alert to a process operator.
:, and its current value.
Write
Print sends the message that you specify to the log. Print is the same as Show except that it prints only
the value of each variable without the variable name and colon.
X=1;A="Hello, World";
print(X,A,"foo");
1
"Hello, World"
"foo"
Write sends the message that you specify to the log. Write is the same as Print except that it suppresses
the quotation marks around the text string, and it does not start on a new line unless you include a return
character yourself with the
write("Here is a message.");
Here is a message.
myText="Here is a message.";
write(myText||" Do not forget to buy milk."); // use || to concatenate
write("\!NAnd bread."); // use \!N for return
Here is a message. Do not forget to buy milk.
And bread.
\!N escape sequence.
The sequence \!N inserts the line breaking characters that are appropriate for the host environment. For an
explanation of the three line breaking escape sequences, see “Quoted Strings,” p. 28 in the “JSL Building
Blocks” chapter.
56JSL Building BlocksChapter 2
Functions that communicate with users
Send information to the user
Beep
Beep causes the user’s computer to make an alert sound.
Speak
Speak reads text aloud. On Macintosh, Speak has one Boolean option, Wait, to specify whether JMP
should wait for speaking to finish before proceeding with the next step. The default is not to wait, and you
need to issue
Wait(1), you probably want to interrupt execution before too long. If you change it to Wait(0), the
iterations proceed faster than the speaking possibly can and the result sounds strange. On Windows, you
can use a
for(i=99,i>0,i--,
A more practical example has JMP announce the time every sixty seconds:
Wait(1) each time. For example, here is a script certain to drive anybody crazy. With
Wait(n) command to accomplish the same effect.
speak(wait(1),char(i)||" bottles of beer on the wall, "
||char(i)||" bottles of beer; "
||"if one of those bottles should happen to fall, "
||char(i-1)||" bottles of beer on the wall. ")
Caption
// Time Announcer
script = expr(
tod = mod(today(),indays(1));
hr = floor(tod/inHours(1));
min = floor(mod(tod,inHours(1))/60);
timeText = "time, " || char(hr) || " " || char(min);
text = Long Date(today()) || ", " ||timeText;
speak(text);
show(text);
schedule(60,script); // seconds before next script
);
script;
You might use a similar technique to have JMP alert an operator that a process has gone out of control.
Caption brings up a small window with a message to the viewer. Captions are a way to annotate
demonstrations without adding superfluous objects to results windows. The first argument is an optional
{x,y} screen location given in pixels from the upper left; the second argument is the text for the window. If
the location argument is omitted, windows appear in the upper left corner.
The
Spoken option causes captions to be read aloud by the operating system’s speech system (if available).
Spoken takes a Boolean argument, and the current setting (on or off ) remains in effect until switched by
another
You can include pauses in the playback by including the named argument
Caption statement that includes a Spoken setting.
Delayed and a time in seconds.
Such a setting causes that caption and all subsequent caption windows to be delayed by that number of
Chapter 2JSL Building Blocks57
Functions that communicate with users
seconds, until a different Delay setting is issued in a Caption statement. Use Delay(0) to stop delaying
altogether.
This script turns speaking on and leaves it on until the last caption.
caption({10,30},"A tour of the JMP Analyses", spoken(1), Delayed(5));
caption("Open a data Table");
bigClass=open("$SAMPLE_DATA/Big Class.JMP");
caption("A JMP Data Table consists of rows and columns of data");
caption("The rows are numbered and the columns are named");
caption({250,50},"The data itself is in the grid on the right");
caption({5,30},spoken(0),"A panel along the left side shows columns and other
attributes");
Each new Caption hides the previous one. In other words, there is only one caption window available at a
time. To close a caption without displaying a new one, use the named argument
caption(remove);
Remove.
StatusMsg
This command sends a message to the status bar.
StatusMsg("string")
Mail
(Windows only)
Mail sends an e-mail message to alert a user about a condition in JMP. For example, a
process control manager might include a test alert script in a control chart to trigger an e-mail warning to
her pager:
mail("JaneDoe@company.com", "out of control", "Process 12A out of control at
"||Format(today(), "d/m/y h:m:s"));
can also send an attachment with the e-mail. An optional fourth argument specifies the attachment.
Mail
The attachment is transferred in binary format after its existence on the disk is verified. For example, to
attach the
Big Class.jmp data table, submit
mail("JohnDoe@company.com", "Interesting Data Set", "Have a look at this class
data.", "C:\myJMPData\Big Class.jmp");
58JSL Building BlocksChapter 2
Functions that communicate with users
Chapter 3
Programming Functions
Script Control
Sometimes you might need to program repetitive operations, or perhaps implement some statistical test that
are not part of JMP. Then you need to learn some of the functions that control flow.
The following functions take on the roles that in other programming languages have statements with special
syntactic structure. They are just functions in JSL, like any other functions, with arguments separated by
commas.
This chapter covers basic programming functions and variables. The chapter “Advanced Concepts,” p. 385,
covers more advanced techniques, such as throwing and catching exceptions and working with expressions.
Here is an example script using JSL to implement a statistical method, a type of runs test. A flow-control
function,
The first statement opens a JMP data table. The Summarize function obtains the mean and count for the
column height.
values. Then it finds n1, the number of heights greater than the mean; n2, the remaining number; and r, the
number of adjacent heights that are not both above or both below the mean. The muR and sigmaR are the
mean and standard deviation of the test statistic under the hypothesis that there is no run pattern, zTest is
the normal test statistic, and p Value is the significance level of the test. If there is a pattern across time, then
neighboring values would be more likely to be alike in whether they were above or below the mean.
Summation, is also used to iterate computations over many rows at a time.
NRow gets the number of rows, which is the same as the count n, since there are no missing
Iterating
JSL provides For, While, Summation, and Product to iterate actions according to the conditions that you
specify.
To iterate actions over rows of a data table, use
chapter.
For
The For function first evaluates init expression, but just one time. Then it tests the while expression,
breaking if not true. As long as the while expression is true, it keeps executing the body and iter expressions.
For
For Each Row, which is discussed in the “Data Tables”
For(init, while, iter, body);
loops just like it does in the C (and C++) programming language, although the punctuation is different.
Confusion alert! If you know C, watch out for the difference between JSL and C in the
use of semicolons and commas. In JSL
arguments and semicolons join them; in C
For is a function where commas separate
for is a special clause where semicolons
separate arguments and commas join them.
62Programming FunctionsChapter 3
Iterating
For example, you can do a Distribution on the first three columns of the current data table:
for(i=0, i<3, i++, Distribution(column(i+1)));
This loop does the following:
1. Sets i to 0.
2. Evaluates 0<3 as true.
3. Launches the Distribution platform for the first column.
4. Increments i to 1.
5. Evaluates 1<3 as true.
6. Launches the Distribution platform for the second column.
7. Increments i to 2.
8. Evaluates 2<3 as true.
9. Launches the Distribution platform for the third column.
10. Increments i to 3.
11. Evaluates 3<3 as false.
12. Breaks out of the loop.
Of course, it is not hard to write scripts that get into infinite loops. When this happens, you can use the
keyboard cancel sequence to get out of the loop (press ESC on Windows, or press COMMAND-PERIOD
on Macintosh).
The following expression sums the numbers from 0 to 20:
s=0; For(i=0, i<=20, i++, s=s+i);
The For loop works like this. It expects four arguments separated with commas ( , ). The first three
arguments are rules for how many times to repeat the loop, and the fourth is what to do repeatedly. This is
where the action takes place.
1. First it sets an initial condition or state. In this case, it assigns the value 1 to a variable i. The first
argument of a for loop is always a starting condition like this one, but the variable and the value could be
anything.
2. Next it tests whether the second argument,
i<=20, is true. If it is true, then it does the action script. If
false, it ends the for loop and continues with the rest of the script (if there is more waiting after the last
parenthesis of the for loop). The second argument is always a condition, like a little
If test. Usually the
condition involves the same variable initialized in the first argument, but that is not always the case. Be
careful not to create an infinite loop. (If you make a mistake, you can press ESC on Windows or
COMMAND-PERIOD on Macintosh to stop the looping.)
3. The third argument is what to do after completing the actions; typically it increments i (adds one to its
current value). The actions are everything that comes next inside the for’s parentheses. You come back to
this in step 5.
4. The fourth argument does the work of the for loop. In this case, it replaces
s with s+i. Only one
command statement is expected in the fourth argument. If you want to do several things on each step,
Chapter 3Programming Functions63
Iterating
glue the statements together with semicolons ( ; ). Semicolons let numerous things stand in place of one
thing.
5. Now the third argument kicks in. After the action of the fourth argument is done, the counter variable i
is incremented, and the execution starts over at the second argument, testing again whether
i<=20 is
still true.
While
A related function is While, which repeatedly tests the condition and executes its body script as long as the
condition is true.
While(condition, body);
For example, here are two different programs to find the least power of 2 that is greater than or equal to x:
The Summation function adds up the body results over all i values. For example:
s = Summation(i=0,10,i); // 0+1+2+....+9+10
This is the same idea as Σ in the calculator except that with Summation, you do not need to restrict yourself
to creating formula variables.
Summation(i=1, NRow(), x^2);
This is the JSL equivalent in the formula calculator:
NRow
2
i 1=
x
∑
Product
The Product function works just like Summation, except that it multiplies the body results rather than
adding them.
p = Product(i=1,5,i); // 1*2*3*4*5
This is the JSL equivalent of this in the formula calculator:
5
i
∏
i 1=
Break and Continue
Two functions give you further control over looping: Break() and Continue(). These two functions work
with For and While loops, and also with For Each Row.
64Programming FunctionsChapter 3
Conditional functions
Break
Break immediately stops the loop and proceeds to the next command after the loop. This is usually used
Without the If statement that contains Break, the loop would print out the values of i from 1 to 10, and
then
“Finished”. However, as soon as i reaches 5, the loop is immediately halted (before the print
statement, but after
If the
If and Break statements were at the end of the loop, the final value of i printed to the log would be
i is 5) and the following statement is processed (Show(“Finished”)).
5 rather than 4.
Continue
Continue is a gentler form of Break. It immediately stops the current iteration of the loop, but sends
execution back to the beginning of the loop rather than stopping the loop completely.
Continue is also
usually used inside a conditional statement. For example:
For( i = 1, i <= 10, i++,
If( i < 5, Continue() );
Print( "i=" || Char( i ) );
);
This loop iterates through i, but until i is greater than 5, the print statement is not executed. There is no
point to placing a
Continue at the end of a loop. The entire loop body has already been executed, so there
is nothing to skip. The loop continues anyway.
Conditional functions
JSL provides five functions to execute script conditionally: If, Match, Choose, Interpolate, and Step.
If
The If function returns the result statement(s) when condition evaluates as true (nonzero and nonmissing).
Otherwise it skips ahead and returns the next result when that condition evaluates as true. The final result is
the result if none of the preceding conditions are true. It is the “else” result.
If ( condition1, result1, condition2, result2, ...., resultLast )
If at least one condition evaluates to missing, the function keeps on evaluating and only returns missing
(rather than evaluating the
returned missing. The way to get a clause to always return despite missing conditionals is to add a
conditional at the end that is always true. For example,
else clause) if none of the clauses evaluated to true and at least one conditional
Chapter 3Programming Functions65
Conditional functions
If (age<12,"Young", a>12,"Old", 1,"Ageless");
For example, the following code sets X to Y if Y is less than 20. Otherwise, it sets X to 20.
X = If(Y<20,Y,20);
You can use this to recode ranges, for example:
row()=1; Age Group = If (Age<12,"Child",Age<18,"Teen","Adult");
You can put actions and assignments in the result clauses, and you do not have to return a result. For
example the following two are equivalent:
X = If(y<20,y,20);
If(y<20,x=y,x=20);
Similar conditionals are Choose and Match.
Match
Be careful to use
== for equality tests, not =. An If with an argument like name=value would assign the
value rather than test it.
You can use The Match function to make a sequence of equality comparisons without needing to rewrite
the value to be compared. The result of the first operand is compared to each of the succeeding even
operands, except the last. If they are equal, the value of the operand immediately after is returned. If nothing
matches, then the last operand is returned. For example:
SLabel = Match(SCode,
1,"Male",
2,"Female",
"unknown");
This would be equivalent to the following If expression:
SLabel = If(SCode==1,"Male",
SCode==2,"Female",
"unknown");
With more groups, the value of Match becomes more apparent:
dt=open("$SAMPLE_DATA/Big Class.JMP");
for each row(ageword=
If a has integer values 1, 2, 3, ..., you can save even more typing by using Choose.
66Programming FunctionsChapter 3
Conditional functions
Confusion alert! If and Match now handle missing values differently than in JMP
version 3.x (as do
result for
Match); now they return missing values, as discussed under “Missing
And and Or ). Previously missing values returned false (the “else”
Values,” p. 82.
Choose
The Choose function can be used to shorten certain recoding even more, provided the arguments are to be
tested against integers 1, 2, 3, and so forth. If the first argument evaluates to 1,
replacement value; if it is 2, the second, and so on. If the first argument evaluates to an integer out of range
(for example, 7 when only 5 replacement values are listed),
example:
SLabel = Choose(SCode,"Male","Female","Unknown");
Thus, if group is a column with values 1, 2, and 3, the following all accomplish the same task, replacing 1s
with “low,” 2s with “medium,” and 3s with “high.”
Figure 3.1 shows a plot of what the interpolation function would look like (dashed line), compared with
what the continuous version (solid line), which is what is being approximated.
Figure 3.1 Example of Interpolate
Step
The points must be arranged in ascending order. For example, Interpolate(2,1,1,3,3) returns 2.
However,
Step is like Interpolate except that it finds the corresponding y for a given x from a step-function fit
Interpolate(2,3,3,1,1) returns a missing value (.).
rather than a linear fit between points. That is, it returns the y-value corresponding to the greatest x-value
that is less than or equal to the x specified as the first argument.
As with Interpolate, the points must be in ascending order.
68Programming FunctionsChapter 3
Controlling script execution
Controlling script execution
When you run a script, the Run Script command in the Edit menu changes to Stop Script. While a script
is executing, you can select this item (or type ESC on Windows or COMMAND-PERIOD on Macintosh)
to stop it. Many scripts execute more quickly than you can stop them.
Wait
Stopping a script manually stops the entire script completely. In contrast, the Wait command enables you
to pause script execution for a time and then continue running the script. This approach is sometimes
necessary for scripts intended for interactive use or demonstrations.
Wait enables you to slow down scripting playback by pausing the specified number of seconds before
continuing with the script. For example, this is a 15-second timer:
Wait(15);
Wait also yields to the system, so that system tasks can be run while waiting. This includes updating the
contents of the screen. Issuing a wait time of 0 (
any longer than needed to do these events. Waiting zero seconds is useful for allowing results to be displayed
right away; otherwise JMP waits for the script to end before yielding to the system to update windows.
Wait(0)) lets JMP to do other pending events, but not wait
Schedule
Schedule runs commands or entire scripts at the times that you specify. See the “Extending JMP” chapter.
JSL Data Structures
Besides numbers and strings, JSL provides several other data types variables can hold:
•Lists
•Matrices
•Associative Arrays
Lists
Lists are containers to store numerous items, potentially items of different type: numbers, text strings,
expressions, matrices, and even other lists. A list is just the function
for
List is to use curly braces. Thus the following two statements are equivalent:
A = List(1,2,B,sqrt(3));
A = {1,2,B,sqrt(3)};
When you define or evaluate a list, it just returns a copy of itself. It does not evaluate items inside the list.
For example, this step reveals that the list contains the variable B, not its current value:
List with arguments. The shorthand
Chapter 3Programming Functions69
JSL Data Structures
B=7;show(A);
A = {1,2,B,Sqrt(3)}
Use Eval List if you want a list with all its items evaluated:
C = Eval List(A);
{1, 2, 7, 1.732050807568877}
Lists can also hold assignments ({a=1, b=2}), or function calls ({a(1), b(2)}). Remember, statements
such as these just return lists. If you want to evaluate the contents, use
h = Function({x},x + 2)
i = Function({x},x + 3)
k = Function({x},x + 4)
show(fnList);
fnList = {h(1), i(3), k(5)}
Eval List.
Assignment
List assignment is powerful.
Note that any structure of a list is supported, as long as the arguments are conformable and ultimately
numeric. One-element lists are treated like scalars for conformability. For example,
{a,b,c} = {1,2,3}; //assigns 1 to a, 2 to b, 3 to c
{a,b,c}+=10; //adds 10 to each variable a, b, and c.
{{a},{b,c}}++; //increments a, b, and c by 1
{a,b,c}--; //decrements a, b, and c
mylist={1, log(2), e()^pi(), height[40]};
// stores the expressions in a list
To determine the number of items in a list, use the
Subscripts
Subscripts for lists extract the specified item(s) from a list. Subscripts can in turn be lists. Note that JSL
starts counting from 1, so the first element in a list is [1], not [0] as in some other languages.
You can also use subscripts to select or change items in a list.
When you have assignment lists or function lists, you can use a quoted name for the subscript:
You need to put the name in quotation marks, because otherwise JMP would try to evaluate it and use its
value, like this:
NItems function:
N = N Items(A);
a={"bob", 4, [1,2,3], {x,y,z}};
show(a[1]); // returns "bob"
show(a[{1,3}]); // returns {"bob",[1,2,3]}
a[2]=5; // changes the 4 to 5
c={1,2,3};
c[{1,2}]={4,4}; // changes c to {4,4,3}
c[{1,2}]=4; // equivalent
Loc(nameList, “Erin”) returns [], an empty matrix, since there are no matches.
Loc(nameList, “Jane”) returns [3, 4]
Loc(nameList, 1) returns []. Note that the type mismatch is tolerated.
Loc(numList, 1) returns []
Loc(numList, 6) returns [3]
Loc(numList, 8)
returns [4, 5]
returns [1]
Here is a summary of the list operators:
Ta bl e 3 .1 Operators for working with lists
OperatorSyntaxExplanation
{}ListList(a, b, c)
{a, b, c}
Constructs a list from a set of items. An item can be any
expression, including other lists. Items must be separated by
commas. Text strings should either be enclosed in double
quotation marks (
that variable.
N ItemsN Items(list)
Returns the number of elements in the list specified. Can be
assigned to a variable.
"") or stored in a variable and called as
72Programming FunctionsChapter 3
JSL Data Structures
Ta bl e 3 .1 Operators for working with lists (Continued)
OperatorSyntaxExplanation
Is ListIs List(arg)
[]Subscriptlist[i]
x = list[i]
list[i] = value
a[b,c]
Subscript(a,b,
c)
Assign
=
Add To
+
=
SubtractTo
-
MultiplyTo
=
DivideTo
*
Post
=
Increment
/
Post
=
Decrement
+
+
-
-
{list} = {list}
{list} –= value
{list} += {list}
...
Returns true (1) if arg is a classical list (in other words, one
that would result from the construction by
{items}) and returns false (0) otherwise. An empty list is still a
list, so
IsList({ }) returns true. If miss=., then
IsList(miss) returns false, not missing.
List(items) or
Subscripts for lists extract the ith item from the list. Subscripts
can in turn be lists or matrices.
If the target of an assignment operator is a list and the value
to be assigned is a list, then it assigns item by item. The
ultimate values in the left list must be L-values (in other
words, names capable of being assigned values).
Note: If you want to test equality of lists, use
==, not =.
Eval ListEval List(list)
Matrices
Matrices can be used to represent values in a data table as well as matrix algebra. See the “Matrices” chapter
for details.
Associative Arrays
An associative array associates unique keys with values, which might not be unique. Though associative
arrays are generally not ordered, JMP keys are returned in lexicographical order for the purpose of iteration
and serialization.
To create an empty associative array, use one of the following:
Returns a list of the evaluated expressions inside list; see
“Lists,” p. 68.
Chapter 3Programming Functions73
JSL Data Structures
cary = [=>];
cary = Associative Array();
The keys and values can be any JSL objects. Items can be added and changed with subscripting:
Use <<Get Default Value to determine whether there is a default value set for an associative array, and if
so, what its value is. If there is no default value set,
Empty() is returned.
Obtaining information about an associative array’s contents
Contains can be used to determine whether a certain key is contained inside an associative array:
Contains(cary, “high schools”)
1
Contains(cary, “lakes”)
0
Several messages provide information about the associative array’s contents.
Use
<< Get Keys to obtain a list of all keys contained in an associative array.
cary <<Get Keys;
{"county", "high schools", "population", "state"}
Likewise, <<Get Values returns a list of all values:
To iterate through as associative array, use
from the associative array
currentkey = cary <<First;
total = N Items(cary);
for (i = 1, i <= total, i++,
);
Sets
A set is an application of an associative array in which all the keys have a value of 1 and non-keys have an
implicit value of 0.
To facilitate set usage, 1 is the default value for inserted keys if no value is provided:
map << insert("sample");
map["sample"];
If you construct an associative array from a list, then the default value is set to 0 for you. Otherwise, you
need to set the default value to 0 explicitly.
Graph Theory
Associative arrays can be used for graph theory data structures, such as the following directed graph
example:
<<First and <<Next. The following removes all key-value pairs
cary, leaving an empty associative array.
nextkey = cary<<Next(currentkey);
Remove From (cary, currentkey);
currentkey = nextkey;
The first parameter is a reference to the map, the second is the node that you want to use as the starting
point, and the third is simply a vector that the function uses to keep track of nodes visited. To see how this
function works try the following:
dfs( g, 2, J( N Items( g << get keys ), 1, 0 ) );
Character Functions
This section shows how to use some of the more complex character functions that are described in the “JSL
Syntax Reference,” p. 439.
Concat
In the Concat function, expressions yielding names are treated like character strings, but globals that have
the name values are evaluated. The following example demonstrates that if you have a stored name value,
you need to either use
n = { abc };
c=n[1] || "def";
show(c);
//result is "abcdef"
m=expr(mno);
c = m || "xyz";
show(c);
//result is an error message that mno is unresolved
m = expr(mno);
c = Name Expr(m) || "xyz";
show(c);
//result is "mnoxyz"
m=char(expr(mno));
c=m || "xyz";
show(c);
//result is "mnoxyz"
Char before storing it in a global, or Name Expr on the global name.
78Programming FunctionsChapter 3
Character Functions
Munger
Concat Items()
converts a list of string expressions into a single string, with each item separated by a
delimiter. If unspecified, the delimiter is a blank. Its syntax is
resultString = Concat Items ({list of strings}, <“delimiter string”>);
For example,
a = {“ABC”, “DEF”, “HIJ”};
result = Concat Items(a, “/”);
returns
“ABC/DEF/HIJ”
Alternatively,
result = Concat Items(a);
returns
“ABC DEF HIJ”
Munger works many different ways, depending on what you specify for its arguments:
Munger(string, offset, find | length, <replace>);
Ta bl e 3 .2 Munger behaviors for various types of arguments
Find, length, and replace argumentsExample
If you specify a string as the find and specify no
replace string,
Munger returns the position (after
offset) of the first occurrence find string.
If you specify a positive integer as the length and
specify no replace string,
Munger returns the
characters from offset to offset + length.
If you specify a string as the find and specify a
replace string,
Munger replaces the first occurrence
after offset of text with replace.
If you specify a positive integer as the length and
specify a replace string,
Munger replaces the
characters from offset to offset + length with replace.
If you specify a positive integer as the length, and
offset + length exceeds the length of text, Munger
either returns text from offset to the end or replaces
that portion of text with the replace string, if it
exists.
Munger("the quick brown fox", 1,
"quick");
5
Munger("the quick brown fox",1,5);
"the q"
Munger("the quick brown fox", 1,
"quick", "fast");
"the fast brown fox"
Munger("the quick brown fox", 1, 5,
"fast");
"fastuick brown fox"
Munger("the quick brown fox",5,25);
"quick brown fox"
Munger("the quick brown fox",5,25,
"fast");
"the fast"
Chapter 3Programming Functions79
Character Functions
Ta bl e 3 .2 Munger behaviors for various types of arguments (Continued)
Find, length, and replace argumentsExample
Repeat
If you specify zero as the length and specify no
replace string,
Munger returns a blank string.
If you specify zero as the length and specify a
replace string, the string is inserted before the offset
position.
If you specify a negative integer as the length value
and specify no replace string,
Munger returns all
characters from the offset to the end of the string.
If you specify a negative integer for length and
specify a replace string,
Munger replaces all
characters from the offset to the end with the
Munger("the quick brown fox", 1,
0);
""
Munger("the quick brown fox", 1, 0,
"see ");
"see the quick brown fox"
Munger("the quick brown fox", 5,
-5);
"quick brown fox"
Munger("the quick brown fox", 5,
-5, "fast");
"the fast"
replace string.
The Repeat function makes copies of its first argument into a result. The second (and sometimes a third)
argument is the number of repeats, where 1 means a single copy.
If the first argument evaluates to a character value or list, the result is that many copies.
repeat("abc",2)
"abcabc"
repeat({"A"},2)
{"A","A"}
repeat({1,2,3},2)
{1,2,3,1,2,3}
If the first argument evaluates to a number or matrix, the result is a matrix. The second argument is the
number of row repeats, and a third argument can specify the number of column repeats. If only two
arguments are specified, the number of column repeats is 1.
repeat([1 2, 3 4],2,3)
[ 1 2 1 2 1 2,
3 4 3 4 3 4,
1 2 1 2 1 2,
3 4 3 4 3 4]
repeat(9,2,3)
[ 9 9 9,
9 9 9]
The repeat function is compatible with the function of the same name in the SAS/IML language, but is
incompatible with the SAS character DATA step function, which repeats one more time than this function.
80Programming FunctionsChapter 3
Character Functions
Sequence
Sequence() corresponds to the Sequence function in the Formula Editor and is used to fill the cells in a
data table column. It takes four arguments and the last two are optional:
Sequence(from, to, stepsize, repeat)
From and to are not optional. They specify the range of values to place into the cells. If from = 4 and to
= 8
, the cells are filled with the values 4, 5, 6, 7, 8, 4, ...
Stepsize is optional. If you do not specify a stepsize, the default value is 1. Stepsize increments the values
in the range. If
8, 4, 6, ...
Repeat is optional. If you do not specify a Repeat, the default value is 1. Repeat specifies how many times
each value is repeated before incrementing to the next value. If
stepsize values, the cells are filled with the values 4, 4, 4, 6, 6, 6, 8, 8, 8, 4, ... If you specify a Repeat
value, you must also specify a Stepsize value.
The sequence is always repeated until each cell in the column is filled.
Example:
// Create a new data table
dt = New Table("Sequence Example");
stepsize = 2 with the above from and to values, the cells are filled with the values 4, 6,
repeat = 3 with the above from, to, and
// Add 2 columns and 50 rows
dt << New Column("Count to Five");
dt << New Column("Count to Seventeen by Fours"); dt << Add Rows (50);
/* Fill the first column with the data sequence 1, 2, 3, 4, 5, ...
Fill the second column with the data sequence 1, 1, 5, 5, 9, 9, 13, 13, 17, 17,
Since Sequence() is a formula function, you can also set a column's formula to use Sequence to fill the
column. This example creates a new column named “Formula Sequence” and adds a formula to it. The
formula is a sequence that fills the column with values between 25 and 29, incremented by 1, and repeated
twice (25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 25, ...).
dt << new column("Formula Sequence", formula(Sequence(25, 29, 1, 2)));