Hey Guys,
I have three methods that do exactly the same thing but operate on three object different variables. The methods look like this:
def meth1 : List[String] = {
if (var1.isDefined) return var1.get
var1 = Some( expensive_filelist_op( "ext1" ) )
var1.get
}
My bright idea was to refactor like this:
def common_ops( wrapper : MyMutator, ext : String ) : List[String] = {
if (wrapper.field.isDefined) return wrapper.field.get
wrapper.field = Some( expensive_filelist_op( ext ) )
wrapper.field.get
}
case class MyMutator( var field : List[String] )
def meth1 : List[String] = common_ops( MyMutator( var1), "ext1" )
def meth2 : List[String] = common_ops( MyMutator( var2), "ext2" )
def meth3 : List[String] = common_ops( MyMutator( var3), "ext3" )
Of course, this didn’t work and the values of var1, var2, and var3 are being recalculated on each invocation. Any ideas would be appreciated.
Is your method only supposed to calculate the value, when it is first accessed? If yes, maybe a lazy val
is all you need:
lazy val var1: List[String] = expensive_filelist_op( "ext1" )
The lazy
modifier will cause your expensive operation to not be called until var1
is used.
Btw., the reason your implementation recalculates everytime is, that you create your MyMutator
containers inside your methods. You’d have to pull these out to some (private) vals.
1 Like
Would var1.getOrElse(expensive_filelist_op( "ext1" ))
give the result you want?
My first advice would be to try not to use vars. But assuming you have good reasons to use vars or that your real use-case is more complex than this example: you can abstract over a var by using 2 function values, get
and set
.
def common_ops(get: => Option[List[String]], set: Option[List[String]] => Unit, ext : String): List[String] = {
if (get.isDefined) return get.get
set(Some(expensive_filelist_op(ext)))
get.get
}
def meth1 : List[String] = common_ops(var1, var1_=, "ext1")
1 Like
Thanks for the detailed response crater2150. You were bang on in both of your answers. I hadn’t fully appreciated how awesome lazy val
was:")