Expressions and LuaXP Functions
-
@toggledbits , I notice that the expression
A = [1,2,3], push(A,A)
does not generate an error (it should, since
push(a,b)
expects a non-object in b), nor does it generate a result. Just limbo. -
toggledbitswrote on Mar 30, 2021, 2:10 PM last edited by toggledbits Mar 30, 2021, 10:11 AM
This will fall into the categories of "don't do this" and "will not be fixed". The reason is objects (which arrays are) pass by reference so that (in more typical usage)
push(A, 55)
can fulfill its definition: modifying A in place by appending 55 to it. An attempt to fix it would result in having to pass copies of the arguments (pass by value), which means the first argument then is not A, but rather a copy of A, and thenpush()
is modifying the copy in place and not the original array, so the original array never changes, defeating the purpose of the function. -
Forging ahead with more newfangled expressions...
@toggledbits what would you expect from:a=["a","b","c"], b=["d","e"], each val in b: push(a,val)
My money was on:
["a","b","c","d","e"]
but instead I got:
[["a","b","c","d","e"],["a","b","c","d","e"]]
EDIT: Ah, here's the magic sauce:
a=["a","b","c"], b=["d","e"], each val in b: c = push(a,val), c
Result:
["a","b","c","d","e"]
-
While you're here...
testArr =
[1,2]
,
firstm
in testArr withm
<=2
Result: (number)1
// correct results since 21089+ -
@toggledbits , I see the immediately-above situation has been rectified with 21090, so I'll edit accordingly.
I also see that you've instantiated some of the array- and text-handling functions you mentioned earlier, so THANK YOU!
For example:
concat( [1] , [2] )
now yields[1,2]
slice( [1,2,3] , 1 , 2 )
now yields[2,3]
pop( [1,2,3] )
now yields3
push( [1,2,3] , 5 )
now yields[1,2,3,5]
shift( [1,2,3] )
now yields1
unshift( [1,2,3] , 5 )
now yields[5,1,2,3]
// NOTE: currently only permits a single addend; for instance,unshift( [1],2,3,4 )
results in[2,1]
not[2,3,4,1]
! -
This one has me scratching my head a bit:
b = [ ] , each i in a = [ 1 , 2 ] : do push( b , i ) , push( b , i ) done
// yields
[[1,1,2,2],[1,1,2,2]]
// expecting[1,1,2,2]
while this modified version:
b=[],each i in a=[1,2]: do push(b,i) done
// yields
[[1,2],[1,2]]
// expecting[1,2]
-
The result of push is an array.
-
@toggledbits said in Expressions and LuaXP Functions:
The result of push is an array.
But if you
push ( [ ] , 1 )
shouldn't you get
[ 1 ]
? And not[ [ 1 ] , [ 1 ] ]
? -
It depends on what the complete expression is. Remember that the value of
each
is every non-null expression result during the iteration. So an array of arrays is a very possible response. -
@toggledbits Unless I'm mis-reading the way
each
works, I had anticipated the underlying interpretation of:b=[],each i in a=[1,2]: do push(b,i) done
to be as follows:
"Start with an empty array namedb
. For each item in the array nameda
, starting with1
, append that value into arrayb
. First, you would get[ 1 ]
, and the next iteration, using the2
froma
, append that tob
to yield[ 1 , 2 ]
."Any I missing an important piece of the puzzle? (I do recognize that
do
/done
is not necessary here, but I left it in for direct comparison with the expression immediately preceding.)Thanks. Sorry to give you grief over these operations.
-
toggledbitswrote on Apr 4, 2021, 3:57 PM last edited by toggledbits Apr 4, 2021, 11:59 AM
If you want to see what b looks like at the end, you need to do this:
b=[],each i in a=[1,2]: do push(b,i) done, b
If you don't (which is how you've done it so far), you are seeing the result of
each
, which is an array, and since each expression within theeach
has resulted in an array, the result of thateach
is therefore an array of arrays, and referring to the same array by reference. -
Makes perfect sense now. Thanks!
-
This one seems to evade the purpose of
isnull()
somehow:isnull(1/a) // returns false
whereas
isnull(a) // returns true, as expected
In both cases,
a
is undefined.I also cannot seem to create an expression that results in true for
isNan()
, no matter what I throw at it.Finally, why would
bool(null)
return TRUE? -
isNaN([1,2,3]) and isNaN("ten"/2) and isNaN("ten" + "eight") are all true
-
toggledbitswrote on Apr 4, 2021, 7:14 PM last edited by toggledbits Apr 4, 2021, 4:17 PM
null coerces to zero (0) for arithmetic operations, so
1/null
is infinity which is not null.int("abc")
results in NaN which will returnisNaN(int("abc"))==true
bool(null)
should return false and I will fix it.Edit: just to follow up, I've added
Infinity
as a keyword/value to the grammar, with a supportingisInfinity(value)
test function (you can also test viavalue === Infinity
), and added that to the documentation for the next release/build. Andbool(null)
is fixed. FYI,bool()
takes a slightly deeper view of "truthiness" than JavaScript natively: the values (number) 0, null, empty string ("") and NaN are false as in JavaScript, but so additionally in lexpjs/Reactor are string "0", string "no", string "off", and string "false"; any other value of any type is true (including empty arrays and objects). -
MSR RECIPES: Compact object-based message composer
Several of my Rules send out SMTP emails, and I'm always looking for a compact method of composing these outbound messages, using the fewest expressions along with a simple "mail merge" template. Here's a two-variable approach you might consider:
msgBody ► "This is my message." // leave blank if msgBody will be set by other Rules msgTemplate ► tmp = {hdr:"Header here" , msg:msgBody , ftr:"Footer here" , crlf:"\n"}, send = {message:tmp.hdr+tmp.crlf+tmp.msg+tmp.crlf+tmp.ftr} , send.message
I hope this can be adapted to your workflow somehow!
-
This post is deleted!
-
Can someone please explain how you would create an array within a Rule that does the following:
(a) begins with an expression that is an empty array;
(b) has another expression containing the .dim_level of a given light;
(c) each time the Rule sets (activates/triggers), the value of (b) is pushed into (a)Working example:
First time light gets turned on, the rule runs. Dim level of 50 is pushed onto end of [ ], making it [50].
Next time light turns on, the rule again runs and pushes the dim level of 75 onto array, making it [50,75].
Etc.I can't quite grok where to put my
push ( )
. In a[Set Variable]
using${{ }}
substitution? In an auxiliary Expression? (I've attempted this approach and can only get one iteration along, meaning the array stops growing after 1 element.) And how does one declare an empty array inside an Expression that will otherwise be modified by the Rule, which normally requires it to be blank?Thanks!
@toggledbits , to put this more succinctly, I find myself unable to implement in MSR the construct you laid out here for creating a time series.
-
LibraSunwrote on Apr 18, 2021, 2:13 PM last edited by LibraSun Apr 18, 2021, 11:18 AM
SOLUTION: This works for creating a timed data series in MSR...
test1
:= if go=="1" then push( test1 , getEntity( "vera>device_110" ).attributes.dimming.level , 5 ) else test1 endif...BUT...you must first pre-populate thetest1
variable with an empty array[ ]
,SAVE
, then paste in the above definition. Otherwise, MSR will throw a "no such 'push' function on (null)" error! (I call this the "Chicken and the Egg" conundrum, whereas Reactor for Luup doesn't complain about doingpush
to a non-existent array; it just invisibly creates one for you.)In my
set
reaction, I do a[Set Variable] [ go ] = 1
, and in thereset
reaction[Set Variable] [ go ] = 0
, with anInterval
imposed on the Rule's sole Trigger condition, making it goTRUE
for 2 seconds every 60 seconds.NOTE: Interestingly, with
Interval
limited to 3 repeats, the variablego
changes to"1"
only 3 times (expected), yet somehow the array gets fully populated with 5 values (unexpected), so I must not fully understand the leading- and trailing-edge nature ofInterval
as it applies to Expression re-evaluation. I'm sure @toggledbits will elucidate? Or is this truly unexpected behavior?ANSWER: Unchecking "Force re-evaluation of expressions and conditions" in both the
set
andreset
reactions cured the problem of "too many data points". There was my problem. -
@librasun said in Expressions and LuaXP Functions:
you must first pre-populate the test1 variable with an empty array
You don't actually. This is just a bug in lexpjs. I've fixed it in my local copy, will be in the next build. It's just this simple: