You have some code that you want to call from more than one place, maybe with different arguments.
Use a user written function, with parameters, local variables to keep them away from other code, and a return statement to send back an answer.
// this example shows how to write a user written function to roll
// ndice with nsides
// a user written function is created with an assignment statement
// to a variable that will be the name of the function. rollDice
// seems a good name to explain what this function does.
rollDice = Function( {ndice = 2, nsides = 6}, // parameters
{i, sum = 0}, // local variables
For( i = 1, i <= ndice, i++, // loop to add up the rolls
sum += Random Integer( 1, nsides ) // one roll
); // end of the loop
Return( sum ); // value to return
); // end of the definition
// make table and distributions. the number of dice
// and the number of sides is chosen to make the
// average roll be 36
dt = New Table( "Untitled",
Add Rows( 10000 ),
// each column has a formula that calls the function...
New Column( "one", Formula( rollDice( 1, 71 ) ) ),
New Column( "two", Formula( rollDice( 2, 35 ) ) ),
New Column( "three", Formula( rollDice( 3, 23 ) ) ),
New Column( "four", Formula( rollDice( 4, 17 ) ) )
);
// check the Std Dev in the 4 reports...
// it gets smaller with more dice
dt << Distribution(
Continuous Distribution( Column( :one ) ),
Continuous Distribution( Column( :two ) ),
Continuous Distribution( Column( :three ) ),
Continuous Distribution( Column( :four ) ),
SendToReport(
Dispatch( {"one"}, "Distrib Histogram", FrameBox, {DispatchSeg( Hist Seg( 1 ), Bin Span( 24, 0 ) )} ),
Dispatch( {"two"}, "Distrib Histogram", FrameBox, {DispatchSeg( Hist Seg( 1 ), Bin Span( 24, 0 ) )} ),
Dispatch( {"three"}, "Distrib Histogram", FrameBox, {DispatchSeg( Hist Seg( 1 ), Bin Span( 24, 0 ) )} ),
Dispatch( {"four"}, "Distrib Histogram", FrameBox, {DispatchSeg( Hist Seg( 1 ), Bin Span( 24, 0 ) )} )
)
);
The Function() function returns a function. The first argument to Function() is a list of parameters, and is required. Use {} if you have no parameters. The parameters can have default values as shown above; rollDice() will use two 6-sided dice. rollDice(3) will use three 6-sided dice, and rollDice(1,7) uses one 7-sided die.
The second argument to function is an optional list of local variables, which can have initial values. By using local values, you can have functions call other functions and not worry about reusing "i" in a for-loop. If you don't need to specify locals, just put the function body as the 2nd argument rather than the third.
The final argument (2nd or 3rd) is the function body. It can reference global values if needed. You can use a return statement anywhere in the body to specify a value to send back to the caller. If there is no return statement, the value of the last statement executed is returned.
The function rollDice is not executed when it is first defined. It is executed when it is called with arguments, like
rollDice(3,6)
which the example does in the column formulas.
http://www.jmp.com/support/help/Advanced_Programming_Concepts.shtml
Thanks for this, @Craige_Hales. When calling the rollDice function, is there a way keep ndice equal to its default value and setting nsides equal to a non-default value without passing in the default value of ndice?
For example:
ndice = 3, nsides = 5 ==> rollDice( 3, 5 )
ndice = 3, nsides = 6 (default value) ==> rollDice( 3 )
ndice = 2 (default value), nsides = 5 ==> rollDice( ?? )
Of course, ndice could be specified ( rollDice( 2, 5 ) ), but does it have to be to allow a non-default value for nsides to be used?
Thanks! @Judah
I'd probably make a rule for a missing value and add an if statement to replace missing with default. rollDice( . , 5 ); which probably means two copies of the default value in the function...
There are several reasons for using default values, and some of them might be bad reasons, sometimes.
The default parameters are probably not any faster than specifying them (untested guess.) It may look better if the default values are what a reasonable code reviewer would expect. Changing the default later might break something. Adding a new parameter for a new caller and not touching the old callers might be useful.
I might be wishing I'd left the default values out of this example; they don't always make code easier to follow. Power tools!
FWIW, I'm glad you left the default values in your example. I came across this post when I was searching for some info on Function(), and this was quite helpful!
If you’re looking for a code snippet or design pattern that performs a common task for your JSL project, the JSL Cookbook is for you.
This knowledge base contains building blocks of JSL code that you can use to reduce the amount of coding you have to do yourself.
It's also a great place to learn from the experts how to use JSL in new ways, with best practices.