Neither is more correct than the other, they mean different things.
val denotes a variable that cannot be reassigned. In C/C++ this would be equivalent to making a variable a
const. In Java it is equivalent to making it
val or its equivalent in other programming languages is a form a defensive programming. It basically lets you state up front that a variable cannot be reassigned and if you forget or have a bug where it does get reassigned the program will throw an error and Designer will underline it in red.
Furthermore, in certain lambdas like in a forEach one can only access vals defined outside the lambda, not vars.
When you have a constant or a val that only gets assigned once (as in this case), or a data structure like a HashMap or StringBuilder where the structure isn’t reassigned but the contents might be,
val should be your choice (IMHO). It is a good habit to get into.
var denotes a variable that can be reassigned. This is used when you are using a variable to hold intermittent values that gets built up over time, a flag that could change later in the rule, and any situation where the variable is intended to be reassigned.
A var defined in a rule or globally cannot be accessed within certain lambdas like forEach (it can be accessed in a Timer). This does provide a challenge because you can’t for example, run a forEach loop and build up a count or something like that into a variable defined outside the forEach.
Unfortunately this is one area where the Rules DSL has some weaknesses. Some problems I’ve encountered:
- the data type of mathematical calculations is BigDecimal, not a primitive like int or float
- if for some reason the Rules DSL cannot convert the actual data type to the data type that is needed it throws a NullPointerException
- there are bugs that pop up periodically that causes calls to the postUpdate or sendCommand actions that leave the vales in their default dataType (e.g. BigDecimal for a Number Item) fails with a NullPointerException whereas sending the same variable using .toString works and/or sending the value using the MyItem.postUpdate, MyItem.sendCommand will work.
Given these problems, there are times where indicating the data type can be helpful, particularly when needing to working around BigDecimal, but in most cases the data type is pretty obvious.
I didn’t include the data type in this case because I didn’t think it was required, though not that I look at it more closely, if
.size really does return an
int then the numOpenWindows.toString wouldn’t work because there is no toString on a primitive.
Are you seeing any errors in the logs?
Try adding a logInfo as the first line of the rule to verify it is getting triggered.
Lets convert the result of the
.size to a Number:
val Number numOpenWindows = new Number(gHouse_Windows.members.filter[w | w.sate.toString != "closed"].size)
Move the logInfo that prints out the value of numOpenWindows before the sendCommand so we can see if there is an error with sending the command verses the counting of the number of open windows.
Try sending numOpenWindows.toString fi the sendCommand seems to be failing.
There is no such thing as a “standard programming”
But if defining the data type feels better please do it. It is actually another form of defensive programming in this context. However, the major drawback will be that you will encounter some data type errors in your rules that would not be errors if you let the Rules DSL figure out and convert data types around for you.