2

AFAIK, Iterator.map is lazy while Vector.map is eager, basically because they are different types of monads.

I would like to know if there is any chance of having a EagerTry and LazyTry that behave just like the current Try, but with the latter (LazyTry) delaying the execution of the closure passed until the result is needed (if it is needed).

Please note that declaring stuff as lazy doesn't work quite well in Scala, in particular it works for a given scope. An alternative exists when passing parameters (parameters by name). The question is how to achieve lazy behaviour when returning (lazy) values to an outer scope. Option is basically a collection of length 0 or 1, this would be an equivalent case for lazy collections (Iterator, Sequence) but limited to length 0 or 1 (like Option and Either). I'm particularly interested in Try, i.e. using LazyTry exactly as Try would be used. I guess this should be analogous in other cases (Option and Either).

Please note that we already have EagerTry, as the current standard Try is eager. Unfortunately, the class is sealed, therefore, to have eager and lazy versions of the same class we would need to define the three of them and implement two of them (as opposed to defining and implementing one). The point is returning a Try without other software layers worrying about the time of execution of that code, i.e. abstraction.

Trylks
  • 1,458
  • 2
  • 18
  • 31

1 Answers1

2

Yes, it wouldn't be hard to write LazyTry. One possible approach:

sealed class LazyTry[A](block: => A) {
  // the only place block is used
  private lazy val underlying: Try[A] = Try(block)
  def get = underlying.get
  def isSuccess = underlying.isSuccess
  ...
}

object LazyTry {
  def apply[A](block: => A): LazyTry[A] = new LazyTry[A](block)
  ...
}

Note that you don't have LazySuccess and LazyFailure, since you don't know which class to use before running block.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
  • Thank you. That covers most of the methods and features of `Try`, but not being able to use pattern matching is a big bummer. For such a use I'd prefer something like [this](http://pastebin.com/g7Bys3gU). In such a case we need to get the actual value before doing anything with it, but it encapsulates laziness just fine, the only problem is: it's not transparent to use it. I even went further as to [try to define a match method](http://pastebin.com/9CkszZGf) but that doesn't work quite well and I'm running out of ideas. – Trylks Feb 25 '15 at 13:56
  • You can convert it to `Try` with `def toTry = underlying` and pattern match that. – Alexey Romanov Feb 25 '15 at 22:57
  • Or add `LazySuccess` and `LazyFailure` objects with `unapply` methods which pattern match on `underlying`. – Alexey Romanov Feb 25 '15 at 23:03
  • WRT converting to underlying, I tried to do that [here](http://pastebin.com/9CkszZGf) with an implicit definition, but it's not implicitly used before matching (note that's a `Lazy` object, which could encapsulate a `Try` obtaining a `LazyTry` or anything else, with the same behaviour). WRT the unapply, AFAIK it makes transparent some computation inside the `Lazy`, I'm trying to make transparent the `Lazy` itself. – Trylks Feb 26 '15 at 13:18