3

Let's say that there is a boolean variable, initially assigned the value false. Is there a way to say, let this variable be true for the next 5 minutes and then let it be false again?

My current idea is that I could store the variable along with a timestamp, then as soon as the variable is turned to true, the timestamp is set to the current time, then check the variable's value through a method that will return true if the current time and the initial timestamp form a duration of less than 5 minutes and then false if the duration is greater than 5 minutes. I'm thinking about an implicit conversion from Boolean to a RichBoolean that would handle this mechanism through an elegant method name or something.

Is there a more elegant or Scala native way of doing this?

Peter
  • 7,020
  • 4
  • 31
  • 51

3 Answers3

5

The timestamp idea is pretty easy to implement (here the argument is in seconds):

class TransientlyTrue(duration: Double) {
  private[this] val createdAt = System.nanoTime
  def value = (System.nanoTime-createdAt)*1e-9 <= duration
}
implicit def TransientToBoolean(t: TransientlyTrue) = t.value

With the implicit conversion you can transparently drop this in wherever you need a Boolean. Or you could leave that off and just call .value.

Rex Kerr
  • 166,841
  • 26
  • 322
  • 407
  • Yeah, so it apparently doesn't get "eleganter". Thanks anyway. – Peter May 29 '14 at 22:41
  • 4
    I always wonder why anybody defaults to nanoTime, rather than to milliseconds, especially given that [nanos may be not accurate enough](http://stackoverflow.com/q/11452597/298389) and harder for humans. What is the reason behind such choose? – om-nom-nom May 29 '14 at 22:41
  • 3
    nanoTime uses a high-resolution date/time independent clock. currentTimeMillis uses the system clock - so if someone resets the date, your timing tends to get messed up. – The Archetypal Paul May 30 '14 at 08:16
5

You may be able to accomplish what you want more elegantly with futures. You won't have a proper variable that's changing its value, but it's not clear that that's an absolute requirement in your question, and you will have a method that starts returning a different value after a certain amount of time. For example, with Twitter's implementation:

import com.twitter.util._
import com.twitter.conversions.time._

implicit val timer = new JavaTimer

val t = Future.sleep(10.seconds)

Now t.isDone will be false for ten seconds and then true. The nice thing about this approach is that you get lots of other combinators on the future that may allow you to solve your problem more directly—see the Scala documentation for more information.

Travis Brown
  • 138,631
  • 12
  • 375
  • 680
  • Note of course that you could also have your future change the value of a `var` when it completes, but I feel like there _must_ be a better way to solve your problem than that. – Travis Brown May 30 '14 at 03:08
-1

Would you be okay with a wrapper object for this? Like TimedBoolean? If so, then you could do something pretty straight forward with either a Timer, or just on your getter and setter do a timestamp check..

To directly answer your question, though, no, there's no Scala native way of doing this. But I'd think that a wrapper method is the "more elegant" way you're looking for.

Christopher Wirt
  • 1,108
  • 1
  • 10
  • 21