exprv4:how-to:use_include_files

How To Use Include Files

Use include files when you want to reuse Expr code from another file.

A good include file can hold functions, classes, constants, or small helper code that is shared by several scripts. This keeps the main script shorter and makes common code easier to maintain.


Create A Small Include File

Create a file with reusable code.

Example file:

// math_helpers.expr
function ToolRadius(diameter)
{
    return diameter / 2;
}
 
function Area(width, height)
{
    return width * height;
}

This file only defines functions. It does not run a job by itself.


Include The File

Use `include` at the top level of another script.

include "math_helpers.expr"
 
radius = ToolRadius(6);
area = Area(40, 25);
 
print(radius);
print(area);

After the include, the functions from `math_helpers.expr` are available in the current script.

The include statement can use a semicolon, but it does not require one.

include "math_helpers.expr";
include "other_helpers.expr"

Include Must Be Top Level

`include` is a top-level statement.

Use it at the script level:

include "math_helpers.expr"
 
print(ToolRadius(6));

Do not put it inside `if`, `while`, `for`, functions, or classes.

if (1)
{
    include "math_helpers.expr"     // error
}

If a script needs different behavior, include the needed files first, then choose what to call with normal `if` logic.


Use Namespace Aliases

For reusable files, prefer including with `as`.

include "math_helpers.expr" as Math
 
radius = Math::ToolRadius(6);
area = Math::Area(40, 25);

The alias keeps included names grouped. This helps avoid name collisions when several libraries define similar function or class names.

Without an alias, included functions and classes are added directly to the current namespace:

include "math_helpers.expr"
 
radius = ToolRadius(6);

This is acceptable for small scripts, but aliases are better for shared libraries.


Include Classes

Include files can also define classes.

Example file:

// probe_job.expr
class ProbeJob()
{
    safe_z = 5;
    feed = 100;
 
    function SetFeed(value)
    {
        feed = value;
    }
 
    function Run()
    {
        return safe_z;
    }
}

Use it from another script:

include "probe_job.expr" as Probe
 
job = Probe::ProbeJob();
job.SetFeed(120);
result = job.Run();

Classes are often the best way to keep related data and workflow code together.


Keep Library Includes Passive

A reusable include file should usually define functions and classes, not start doing work immediately.

Good include file:

// probe_math.expr
function ClearanceZ(surface_z, clearance)
{
    return surface_z + clearance;
}

Risky include file:

// probe_run.expr
safe_z = 5;
feed = 100;
print('probing now');

Top-level statements in an included file run each time the file is included. That can be useful for a runnable script, but it is usually not what you want in a reusable library.


Choose The Include Path

Use a path without a leading dot for a file beside the current source script.

include "math_helpers.expr" as Math
include "probe_steps.expr" as Steps

Use `./` for shared libraries stored in the profile folder.

include "./lib/probing/probe_job.expr" as Probe
include "./lib/atc/tool_change.expr" as ATC

This is important: in Expr path rules, `./` means profile-relative, not source-relative.

Use How relative paths work when you need exact path behavior.


Use Include From MDI

If you run Expr from MDI or another host input, you can include a script file and call code from it.

=include "./lib/probing/probe_job.expr" as Probe
job = Probe::ProbeJob();
job.Run();

In MDI, the leading `=` tells the host to evaluate the input as Expr instead of G-code.

For multi-line MDI input, put the include first so the definitions are available to later lines.


Avoid Duplicate Work

Including the same file more than once is allowed, but it is not treated as `pragma once`.

This means:

  • function definitions can be replaced by later definitions
  • class definitions can be replaced by later definitions
  • top-level statements run again
  • including the same file with different aliases creates separate namespaced definitions

For simple scripts, include each library once near the top of the file.


Avoid Circular Includes

Do not make two files include each other.

Avoid this:

A.expr includes B.expr
B.expr includes A.expr

Prefer this:

probe_job.expr      defines ProbeJob
probe_dialog.expr   defines ProbeDialog
probe_plate.expr    includes both and connects them

The top-level script should connect independent include files together.


For a normal reusable include:

  • put functions or classes in the include file
  • include it at the top level
  • use `as Name` for shared libraries
  • keep the include file passive
  • use `./lib/…` for profile libraries
  • use plain file names for helpers beside the current script
  • let the main script decide what to run

Example:

include "./lib/probing/probe_job.expr" as Probe
 
job = Probe::ProbeJob();
job.SetFeed(120);
result = job.Run();

See Also

exprv4/how-to/use_include_files.txt · Last modified: by 127.0.0.1

Page Tools