Timers in functions not possible?

As someone who has been there and done that, I suspect you will be happier with the results if you instead focusing on making your Rules generic instead of using lambdas. There are a number of limitations with lambdas that make them awkward to work with including:

  • they can only be used from the one .rules file they are defined in
  • they cannot see other global variables meaning you need to pass lambdas you want your lambda to call as an argument (I may have just thought of a workaround for that but it’s ugly so won’t mention it here unless someone asks)
  • errors generated from lambdas are inscrutable and usually relatively meaningless
  • they only support seven arguments

But if you make your Rules generic you avoid duplicated code and the Rules themselves define the separation of the code. Rules can be triggered from any .rules file (depending on how they are triggered). And your Rules code will usually end up shorter.

Anyway, off of my soap box, to your actual question…

That’s because you have to pass myTimer as an argument to myFunction. Global vars and vals are not in scope with eachother (i.e. cannot see each other).

I’m actually surprised it isn’t complaining that myTimer is unknown from the lambda and actually seems to be successfully using it. But that is why it is not getting to the second log statement. It manages to create the Timer but runs into an error attempting to assign it to myTimer since the lambda doesn’t have access to that variable. So it throws and error before it can run the second log statement.

OK, there it is. As you can see, and as I mentioned above, errors generated from inside lambdas are usually inscrutable and unhelpful.

Assuming you are on OH 2.3, there is a slightly cleaner way to define a lambda.

val myFunction = [ String a, String b, Timer = myTimer |
	logInfo("TEST", "Timer: " + myTimer)
	if (myTimer === null) {
		myTimer = createTimer(now.plusSeconds(5), [|
			logInfo("TEST", "Printing String a: " + a)
		])
		logInfo("TEST", "Printing String b: " + b)
	}
]

Now another warning I have is I don’t know if the arguments are passed by reference or by value. So when you use myTimer = createtimer(... I don’t know if the global myTimer gets assigned the new Timer, or if only the local myTimer gets assigned the new Timer and that local myTimer goes away once the lambda exits. I’ve only ever written lambdas that work with collections of Timers so I’ve never had to figure that out.

Oops, @StefanH beat me to it. I’m basically saying the same thing only with a lot more words.

Anyway, I recommend looking at the Design Patterns. In particular:

With these DPs you should be able to achieve your goals without using lambdas.

2 Likes