New function to define local variables - let

80 views
Skip to first unread message

Mathieu

unread,
Feb 9, 2024, 3:11:45 PMFeb 9
to Lightjams
In the new beta version 686 - https://www.lightjams.com/history.html - I'm testing a new function allowing to use variables in your formula. It's only for the current formula and you can't share the variable between formulas.

For example, you can do:

let(a,sin(1), b,pulse(1),
a+b/2)

That means, you define one variable named 'a' with the value of sin(1) and another variable named 'b' with the value of pulse(1). Then the formula a+b/2 uses both variables to compute the result.

Another example, with an original formula like:

xtopercent(counter(0,  2 /* beat multiple */ * grid.lastx,onbeat(trigger(music.2.beat,0.1,10,30,0.2)),0, grid.onactivated /* reset the beat counter */) / 2 /* beat multiple */)

With the let function you can avoid repeating the "beat multiple" value and also replace the comment by a variable with a good name:

let(beatMultiple, 2,
     xtopercent(counter(0,  beatMultiple * grid.lastx,onbeat(trigger(music.2.beat,0.1,10,30,0.2)),0, grid.onactivated) / beatMultiple))

Your feedback is welcome!

Michael Bruus

unread,
Aug 21, 2024, 9:30:32 AMAug 21
to Lightjams
Hi there

While I see the usefulness of naming variables within the let() function, I find it to be too limited to really be of value.
I would really appreciate if it was possible to name mem locations with strings.

Example:
Name instead of id: mem(foo, 100)
Or defning a name along with Id: mem(0, 100, foo)
And then: recall(foo)

This would really help with keeping track of what's going on in complex formulas.

Anyway, I really appreciate the new 'last' function... thanks!

Mathieu

unread,
Aug 26, 2024, 9:19:02 AMAug 26
to Lightjams
Hi,

At least with the let function, it can help you remember what is meaning of your memory ids. For example,

let(foo,0,
mem(foo, sin(10))
)

Michael Bruus

unread,
Sep 8, 2024, 8:53:54 AMSep 8
to Lightjams
FYI I finally ran in to a use case for let()... :-)

Mathieu

unread,
Sep 8, 2024, 9:02:13 AMSep 8
to Lightjams
>> I finally ran in to a use case for let()

Let us know what it is! ;)

Michael Bruus

unread,
Sep 10, 2024, 3:23:45 AMSep 10
to Lightjams

Well, it seems I was way to quick to discard the potential in the let() statement.
I find myself using it all the time now :-)

Here’s an example of a refactured formula, where I’ve used let() in the refactored version.
I can now discard most of the comments, as the variable names now holds the clue to what they contain/represent.
The script is for (one of several) sources powering saturation attributes.

Without let():

/* Fades saturation from 100 to 0 and back to 100 during hue shift from color to white. Makes shift from RTA hue to mix-on color for RGB white without visually cycling through the intervening color space. --- recall(1) = Flag for vox activity per fixture (0|100). Replace +X with fixture index. recall(2) = Hue from RTA (incl. offset). recall(72) = Slider id for Break-White brightness. recall(73) = Slider id for Vox-White brightness. recall(76) = Slider id for fade-in duration of Vox-White. recall(77) = Slider id for fade-out duration of Vox-White. grecall(0) = Flag for break/song state (0|100). grecall(20) = Modified fade-in duration of break-white (song to break). grecall(21) = Modified fade-out duration of break-white (break to song). */ crossfade( /* Fade-in = Song state / Fade-out = Break state. */ fadein.linear(grecall(21), fadeout.linear(grecall(20), if (slider(recall(72)) == 0, 100, grecall(0)))), /* Song state */ if (slider(recall(73)) == 0, 100, min ( abs( /* Fade-in = Vox White / Fade-out = Song color. Replace +X with fixture index. */ fadein.linear(slider(recall(76)), fadeout.linear(slider(recall(77)), recall(1) + 0)) * 2 - 100 ), abs( /* Fade-in = Song state / Fade-out = Break state */ fadein.linear(grecall(21), fadeout.linear(grecall(20), grecall(0))) * 2 - 100 ) ) ), /* Break State */ abs( /* Fade-in = Song state / Fade-out = Break state */ fadein.linear(grecall(21), fadeout.linear(grecall(20), grecall(0))) * 2 - 100 ) )

And here with the let() statement.
It greatly reduces clutter an improves legibility:

/* Fades saturation from 100 to 0 and back to 100 during hue shift from color to white. Makes shift from RTA hue to mix-on color for RGB white without visually cycling through the intervening color space. --- */ let(fixtureIdx, 0, let( /* Local vars */ isDisabledBreakWhite, slider(recall(1)) == 0, isDisabledVoxWhite, slider(recall(2)) == 0, fadeInTimeBreakWhite, recall(3), fadeOutTimeBreakWhite, recall(4), fadeInTimeVoxWhite, recall(5), fadeOutTimeVoxWhite, recall(6), isSongState, !recall(20), /* Inverse Break-white flag so it becomes SongState flag. */ isVoxWhite, recall(50 + fixtureIdx) == 100, /* -100|0|100 */ /* Formula */ crossfade( /* Fade-in = Song state / Fade-out = Break state. */ fadein.linear(fadeOutTimeBreakWhite, fadeout.linear(fadeInTimeBreakWhite, if (isDisabledBreakWhite, 100, isSongState))), /* Song state */ if (isDisabledVoxWhite, 100, min ( abs(fadein.linear(fadeInTimeVoxWhite, fadeout.linear(fadeOutTimeVoxWhite, isVoxWhite)) * 2 - 100), abs(fadein.linear(fadeOutTimeBreakWhite, fadeout.linear(fadeInTimeBreakWhite, isSongState)) * 2 - 100) ) ), /* Break State */ abs(fadein.linear(fadeOutTimeBreakWhite, fadeout.linear(fadeInTimeBreakWhite, isSongState)) * 2 - 100) ) ) )

Mathieu

unread,
Sep 12, 2024, 2:11:24 PMSep 12
to Lightjams
That's really nice! Thanks for sharing.
Reply all
Reply to author
Forward
0 new messages