Expressions Improvements in Version 8

Significant and fundamental changes were made in the way expressions are compiled by Beat Link Trigger starting with version 8. These achieve goals that James had been seeking for years, but had not yet figured out a practical way to implement.

Previously, all expression code was compiled into the Clojure namespace beat-link-trigger.expressions, which is the same place that some important plumbing for compiling the expressions themselves lives. Also, since Triggers window expressions, as well as the expressions for any Show that was ever opened, were compiled into the same namespace, you had to be careful to name shared functions in a lengthy way in hopes they would never overwrite each other, regardless of where they came from.

This also meant that you should not use def to create any of your own variables in the Shared Functions block, and should instead put any data you might need in the separate globals atoms that BLT made available to the Triggers window and to each show.

Now, Triggers window expressions get compiled into their own private namespace, beat-link-trigger.expressions.triggers, and each show that is opened gets a private namespace of its own with a unique name like beat-link-trigger.expressions.SHOW__70112. The globals atoms in each namespace are ordinary atoms defined in that namespace, and you can def your own atoms and other values in your Shared Expressions blocks. This will make your own code more readable and more idiomatic Clojure.

As part of this change, the integration examples have been updated, and are now simpler and easier to understand. They now teach a more typical Clojure style. Some of them needed to be adapted in order to work with this new approach to compilation.

The Triggers Window namespace

This is now the place where all ordinary triggers, as well as any shows’ raw triggers, get compiled. (Those show raw triggers can access shared functions and data from their show using a new show-shared/ alias described below.)

Since this is now private, and no longer has any code used by Beat Link Trigger itself in it, you can be much more free about defining functions and vars for use by all your triggers in your Shared Functions code. (Raw triggers should only use functions and data defined in their show, using the show-shared/ alias, and not mess with what is defined in this namespace.)

You can find the source for the namespace on GitHub. This will also let you see all the functions and namespace aliases that are pre-installed for use by your expressions. (You should still be careful about replacing any of those functions, because some are used by the convenience bindings in the expression editor.)

Show namespaces

These are based on a template as well, which can also be found on GitHub, though the name is made unique when creating a namespace for each show at the time it is opened.

Again, since this namespace is now private to your individual show, you can feel much more free to create functions and vars in your Shared Functions code, without worrying about conflicting with other shows or the Triggers window.

Adapting Existing Code

Although most code should continue to work fine in this new, much safer, world, there are some things that used to be possible that are either no longer recommended (because there are now safer approaches), or that need to be tweaked slightly in order to continue to work.

Accessing Show Shared Code from Raw Triggers

Shows can contribute triggers to the Triggers window when they are open, and those triggers need to work in a coordinated way with the show. In the past, since all shared functions lived in the same namespace, it was possible for the raw trigger code to just call the show shared function directly. Now that code for the Triggers window is compiled in a separate namespace from any show (and this includes raw triggers coming from shows), this will no longer work. To solve that problem, when compiling code for a show’s raw triggers, that show’s namespace is available through the alias show-shared.

So, where you could previously call a function named some-fancy-function defined in the show Shared Expressions from a raw trigger by just invoking it as:

(some-fancy-function …)

you now need to instead use:

(show-shared/some-fancy-function …)

Sharing Show Data with Raw Triggers

Prior to version 8, even when all expressions were compiled into the same namespace, it was still a challenge to share data between expressions that run in the context of the show, and expressions in raw triggers belonging to that show, since those run in the Triggers window, and in that old world, globals was a magic convenience variable, not an ordinary atom defined in a namespace.

The old solution was another special convenience variable, trigger-globals, which was made available when compiling raw trigger expressions, and which provided access to the Triggers window globals.

Although that convenience is still available for now (for backwards compatibility), if any show is opened that still uses it, a warning will be displayed.

You should change any such code so that the show no longer puts things in the Triggers window namespace (because that risks collisions with other shows and ordinary triggers) and instead uses the show-shared mechanism described above to let raw triggers access data they need in their show’s namespace.