Table of Contents

How To Use Sessions Safely

Expr sessions let values, user functions, and user classes persist between separate evaluations.

That is useful for interactive work, custom dialogs, callbacks, and automation scripts, but it also means old state can affect later code if sessions are used casually.

Use sessions deliberately: know who owns the session, what data is allowed to stay there, and when it should be cleared or deleted.


When To Use A Session

Use a named session when state must survive after one evaluation ends.

Good uses include:

Do not use persistent session state for values that should be recalculated every run.

For one-shot scripts, prefer local variables and let the evaluation end without relying on session persistence.


Understand What A Session Stores

A session can store:

Root assignment stores values in the active session:

count = 1;

A later evaluation in the same named session can read `count`.

Local variables created with `set` do not persist after their local scope ends:

{
    set temp = 123;
    print(temp);
};
 
// temp is not a session variable here

Use local variables for temporary calculations. Use session variables only for state that intentionally survives.


Check The Active Session

Before debugging session behavior, print the active session name and stored names:

print('session: ', session.current);
print('variables:');
print(session.list_variables());
print('functions:');
print(session.list_functions());
print('classes:');
print(session.list_classes());

If `session.current` is an empty string, the script is using the fallback session.

Do not assume that every host context uses the same session. The host decides which session is attached to an evaluation.


Use Clear Session Names

Choose session names that describe ownership and purpose.

Good examples:

session.create('probe_setup');
session.create('atc_state');
session.create('dialog_tool_editor');

Avoid generic names for long-lived scripts:

session.create('test');
session.create('tmp');
session.create('data');

Generic names are easy to reuse accidentally. That can mix unrelated variables, functions, and classes.

If a script creates a session for a specific job, include a job id, file name, or other unique part when the host provides one.


Keep Session Changes Near The Entry Point

Joining sessions changes the context for later code. Creating and deleting sessions do not switch context, but they still change session registry state.

For maintainable scripts, do session management near the start or end of the main script:

session.create('probe_setup');
session.join('probe_setup');
 
safe_z = 5;
probe_feed = 100;
 
function ProbeDepth()
{
    // use session state here
    return safe_z;
}

Avoid changing sessions deep inside utility functions. A helper that silently calls `session.join(…)` can surprise callers. A helper that clears or deletes sessions can remove state the caller still expects.

Better pattern: make helpers receive the values they need as parameters, or clearly document that a helper changes the active session.


Avoid Accidental Shared State

A root variable can be changed by any later script that runs in the same session.

This is convenient, but it can also create hidden dependencies:

// first script
feed = 100;
 
// later script in the same session
feed += 25;

If `feed` was meant to be private to the second script, use a local variable:

{
    set feed = 100;
    feed += 25;
};

For reusable functions, prefer parameters over reading random session variables:

function FeedForMaterial(base_feed, material_factor)
{
    return base_feed * material_factor;
}

Use session variables for deliberate shared state, not for avoiding parameters.


Clear Only Sessions You Own

`session.clear()` removes current session variables, user functions, and user classes. Built-in global objects are restored.

print(session.current);
session.clear();

This is useful when resetting a session you own.

It is risky in shared or host-managed sessions because other scripts may rely on that state.

Before clearing:

`session.delete(name)` should also be used only for sessions your script owns.

if (session.current == 'old_probe_job')
{
    session.join('');
};
 
session.delete('old_probe_job');

Use none() To Remove Variables

Assigning `none()` to a session variable clears it.

probe_result = 12.34;
probe_result = none();

This is safer than clearing the whole session when only one value should be removed.

Use this for optional state:

last_error = none();
last_probe_point = none();

See none(), nan(), and errors.


Keep Callback State Explicit

Callbacks can run after the script that created them has returned.

Examples include:

If a callback needs state, store it intentionally.

A class instance is often a clean way to keep callback state together:

class Counter()
{
    Count = 0;
 
    function OnTimer(n)
    {
        Count += 1;
        print('count ', Count);
    }
}
 
counter = Counter();
t = timer(counter.OnTimer);
t.start(1000, 3);

Keep the object in a session variable if it must stay alive after the initial evaluation.

Do not rely on temporary local variables for callback state. Local variables are gone when the evaluation that created them ends.


Keep Sessions Small

Long-lived sessions can accumulate old variables, functions, classes, and objects.

That makes debugging harder and can keep host resources alive longer than expected.

Use these checks during development:

print(session.current);
print(session.list_variables());
print(session.list_functions());
print(session.list_classes());

Practical cleanup rules:


Read From Another Session Carefully

`session.has_variable(sessionName, variableName)` checks whether another session contains a variable.

`session.get_variable(sessionName, variableName)` reads a variable from another session. Object values must be cloneable.

if(session.has_variable('probe_setup', 'safe_z'))
{
    safe_z = session.get_variable('probe_setup', 'safe_z');
}
else
{
    safe_z = 5;
}

Use cross-session reads for inspection or controlled handoff. Avoid making many scripts depend on many other sessions; that creates hidden coupling.


One-Shot Script

Use locals and parameters. Do not rely on persistent state.

{
    set safe_z = 5;
    set feed = 100;
 
    print('safe z ', safe_z);
    print('feed ', feed);
};

Interactive Session

Store only values that should persist between commands.

material = 'aluminum';
default_feed = 250;

Job-Specific Session

Create or join a session owned by the job. Clean it when the job is finished.

Use a fixed name when the job needs to be rejoined by name:

old_session = session.current;
job_session = 'probe_job_001';
 
session.create(job_session);
session.set_variable(job_session, 'old_session', old_session);
session.join(job_session);
 
probe_count = 0;
last_probe_point = none();
 
session.join(old_session);
session.delete(job_session);

Use a generated name when the session only needs to be unique for this run. `str_uuid()` is preferred for uniqueness:

old_session = session.current;
job_session = 'probe_job_' + str_uuid();
 
session.create(job_session);
session.set_variable(job_session, 'old_session', old_session);
session.join(job_session);
 
// use job session here
 
session.join(old_session);
session.delete(job_session);

`str_rand(length)` is also useful for shorter temporary names when a small collision risk is acceptable:

old_session = session.current;
job_session = 'probe_job_' + str_rand(12);
 
session.create(job_session);
session.set_variable(job_session, 'old_session', old_session);
session.join(job_session);
 
// use job session here
 
session.join(old_session);
session.delete(job_session);

Store the generated name if later code must join or delete the same session.

If cleanup happens separately and the job name is fixed, use the name directly after switching away from the active job session:

if (session.current == 'probe_job_001')
{
    session.join('');
};
 
session.delete('probe_job_001');

Library Include

Avoid session management in reusable include files.

Library files should usually define functions and classes, not create, clear, join, or delete sessions.


Common Mistakes

Depending On Old Variables

A script works once because an old variable exists in the session, then fails in a clean session.

Fix: initialize required variables at the start of the script or pass them as function parameters.

Clearing The Wrong Session

`session.clear()` affects the current session. If a previous command changed the active session, the wrong state can be removed.

Fix: print `session.current` before clearing, and clear only sessions owned by the script.

Sharing Generic Session Names

Several scripts use a session named `test` or `tmp` and overwrite each other's values.

Fix: use descriptive names such as `probe_setup`, `atc_state`, or a host-provided job-specific name.

Hiding Session Changes In Helper Functions

A helper calls `session.join(…)` and the caller continues in a different session without realizing it.

Fix: keep session switching at the entry point, or document the helper as a session-management function.


Checklist

Before using a persistent session, answer these questions:


See Also


How-To index: How-To Guides