Apologies for the confusing title, didn’t know how to express it better. This is a follow-up from Overloading in Scala when type parameters are being used
Here’s the faulty code:
def parser[T](identifier: String, default: T, modifier: String => T): T = {
val l = args.filter(_.toLowerCase.startsWith(identifier.toLowerCase))
println("l:")
println(l.isEmpty)
if(l.isEmpty) default
else modifier(l(0).drop(identifier.length).trim)
}
val installation: String = parser("-installation", {throw new Error("Installation not specified")}, identity)
This code is in the main function, so args is the usual list of arguments. If I do pass in a -installation asdf argument what happens is that the error gets thrown before the program can even step into the parser method (This happens becase no “l: false” is printed in the console, so that code is never reached.) I believe the exception is thrown when the
{throw new Error("Installation not specified")}
block is evaluated. I guess Scala evaluates that block in order to know what value to pass to the method. Is there a way of deferring evaluation until it actually hits that bit of the code inside parser?
I’ve tried using a lazy value, something like:
lazy val error = {throw new Error("Installation not specified")}
val installation: String = parser("-installation", error , identity)
but this doesn’t work either.
You need to pass
defaultby-name, with=> T, if you want it to be evaluated only if need beOtherwise, the arg of a function are evaluated when the function is called (call by value). Your lazy val simply causes error to be evaluated when you call parser passing it as argument.
On the other hand, you can use lazy val inside a method, when you do not want a call by name argument to be evaluated each time it is referenced.
In your case, it is not needed, as default is called at most once in parse.