Publication date: 07/08/2024

JSL Namespaces

A namespace is a collection of unique names and corresponding values. You can store references to namespaces in JSL variables. Namespace names are global, because JMP has only one namespace map. Namespace references are variables like any other variable that references an object, so they must be unique within their scope or namespace. The members of a namespace are referenced with the : scoping operator, such as my_namespace:x to refer to the object that is named x within the namespace called my_namespace. See User-Defined Namespace Functions for more information about creating and managing your own namespaces. Namespaces are especially useful for avoiding name collisions between different scripts.

User-Defined Namespace Functions

Create your own namespaces to hold related sets of variables and function definitions. There are several functions that you can use to manage namespaces.

New Namespace

nsref = New Namespace( <"nsname">, <{ name = expr, ... }> );

Creates a new namespace called nsname (a string expression) and returns a reference to the namespace. All arguments are optional.

Nsname is the name of the namespace in the internal global list of namespace names. Nsname can be used as the prefix in a scoped variable. The function returns a reference to the namespace, and can also be used as the prefix in a scoped variable reference. If nsname is absent, the namespace is anonymous and is given a unique name created by JMP. Show Namespace() shows all namespaces and their names, whether assigned or anonymous.

Important: If you already have a namespace named nsname, it is replaced. This behavior means that while you are developing your script, you can make your changes and re-run the script without having to clear or delete your namespace. To avoid unintentional replacement, you can either use anonymous namespaces, or test to see whether a particular namespace already exists:

If( !Namespace Exists( "nsname" ), New Namespace( "nsname" ) );

A list of named expressions is optional. The names are JMP variables that exist only within the namespace.

Note: The named expressions must be a comma-separated list. Separating the expressions with semi-colons causes the list to be ignored.

These namespaces must be uniquely named to prevent collisions in situations where multiple user-defined namespaces are being used. Using anonymous namespace names prevents collisions.

Namespace

nsref = Namespace( "nsname" | nsref);

Returns a namespace reference. The argument might be either of the following:

a quoted string that contains a namespace

a reference to a namespace

Note: Namespace() returns a reference to a namespace that already exists. It does not create a new namespace.

Is Namespace

b = Is Namespace( nsref );

Returns 1 (true) if nsref is a namespace or 0 (false) otherwise.

As Scoped

b = As Scoped( "nsname", var_name);
nsname:var_name;

As Scoped() is the function form of a scoped reference. The function returns a reference to the specified variable in the specified scope.

Namespace Exists

b = Namespace Exists( "nsname" );

Returns 1 (true) if nsname exists in the list of global namespaces, or 0 (false) otherwise.

Show Namespaces

Show Namespaces();

Shows the contents of all namespaces contained in the list of global namespaces. Namespaces are not visible unless a reference is made to one, using either the New Namespace or Namespace functions.

Namespace Messages

In addition to the namespace management functions, a namespace also supports a set of messages to access and manipulate its contents.

Note that these messages, as with all message, must be sent to a scriptable object. A namespace name is not a defined scriptable object and cannot be used in a Send operation. However, you can use the name of a namespace in variable references. For example, nsmane::var is equivalent to nsref::var.

See Namespace Messages in the JSL Syntax Reference for descriptions of the messages that are supported by user-defined namespace references.

Using Namespace References

The following are all equivalent references to a variable that is named b in the namespace that is named nsname that has a reference nsref:

nsref:b
nsname:b
"nsname":b
nsref["b"]
nsref<<Get Value("b") // used as an r-value

Namespaces and Included Scripts

An included script runs in the namespace of the parent script. If the included script has its own namespace definitions, you need to do one of the following:

manage the namespace names to avoid name collisions

use anonymous names created by the New Namespace function

In either case, you still need to manage variable references to namespaces.

There is also an option for the Include function (New Context) that creates a namespace that the included script runs in. This namespace is anonymous and it is independent from the parent script’s namespace. For example:

Include("file.jsl", <<New Context);

This anonymous namespace can be referenced using Here.

If both the parent and included scripts use the global namespace, add Names Default To Here to the New Context option to avoid name collisions. For example:

Include("file.jsl", <<New Context, <<Names Default To Here);

See Include a Script for more information about the Include function.

Examples of User-Defined Namespaces

Creating and Using a Basic Namespace with Expressions

This example shows creating an anonymous namespace and using functions and variables within it.

new_emp = New Namespace(
	{name_string = "Hello, *NAME*!",
 
	print_greeting = Function( {a},
		Print( Substitute( new_emp:name_string, "*NAME*", Char( a ) ) )
	)}
);

Note that you must use the fully qualified name for variables defined within the namespace.

new_emp:print_greeting( 6 );

"Hello, 6!"

Complex Number Operations

This example creates a namespace that contains functions to support using two-element lists to represent complex numbers, and then locks the namespace.

If( !Namespace Exists( "complex" ),
	New Namespace(
		"complex"
	);
	complex:makec = Function( {a, b},
		Eval List( {a, b} )
	);
	complex:addc = Function( {a, b}, a + b );
	complex:subtractc = Function( {a, b}, a - b );
	complex:multiplyc = Function( {a, b},
		Eval List( {a[1] :* b[1] - a[2] :* b[2], a[1] :* b[2] + a[2] :* b[1]} )
	);
	complex:dividec = Function( {a, b},
		d = b[1] ^ 2 + b[2] ^ 2;
		Eval List(
			{a[1] :* b[1] - a[2] :* b[2] / d, a[2] :* b[1] - a[1] :* b[2] / d}
		);
	);
	complex:charc = Function( {a},
		Char( a[1] ) || "+" || Char( a[2] ) || "i"
	);
);
Namespace( "complex" ) << Lock;

Here are examples using functions that are within the above user-defined namespace.

c1 = complex:makec( 3, 4 );
c2 = complex:makec( 5, 6 );
cadd = complex:addc( c1, c2 ); // returns {8, 10}
csum = complex:subtractc( c1, c2 ); // returns {-2, -2}
cmul = complex:multiplyc( c1, c2 ); // returns {-9, 38}
cdiv = complex:dividec( c1, c2 ); // returns {14.6065573770492, 19.7049180327869}
Show( complex:charc( c1 ) ); // returns complex:char(c1) = "3+4i";
cm1 = complex:makec( [1, 2, 3], [4, 5, 6] ); // returns {[1, 2, 3], [4, 5, 6]}
Want more information? Have questions? Get answers in the JMP User Community (community.jmp.com).