Reputation: 15927
I constantly find I need to write function with inner recursive helper function, and it takes the same parameter list as its outer function, but only an additional accumulator argument:
def encode(tree : Tree, text: String):String = {
def rec(tree: Tree, text:String, result:String):String = ???
rec(tree, text, "")
}
I want to simplify this into :
def encode(tree : Tree, text: String)(implicit result:String = "" ):String
this can remove the inner function definition, but it has a problem of that, see if I need to call a function lookup
inside encode
, and lookup
also takes implicit parameter of type String, the implicit result:String = ""
implicitly pass to lookup
function.
def lookup(tree : Tree, text: String)(implicit result:String = "" ):String
I don't want this happen, is there a way to restrict the implicit parameter in lookup
from resolving outside of that function? Or other better ideas?
Upvotes: 0
Views: 139
Reputation: 14842
How about using a normal default argument instead and then passing the accumulator explicitly in the implementation:
def encode(tree : Tree, text: String, result : String = "" ): String = {
//snip
encode(new_tree, new_text, new_result)
}
// call
encode(my_tree, my_text)
Upvotes: 2
Reputation: 7383
Your idea is nice but the use of implicit parameters of such general type is discouraged, lest you stumble into implicit definition conflict (e.g. for too many implicit Strings
visible in your scope).
IIRC, the book from Martin specifically mention such issues.
You could define an explicit Wrapper hierarchy class around your String, whose type changes for each specific method
abstract class Wrapper[A](value: A) { def apply(): A = value }
case class EncodeWrapper[A](value: A) extends Wrapper(value)
case class LookupWrapper[A](value: A) extends Wrapper(value)
def encode(tree : Tree, text: String)(implicit result: EncodeWrapper[String] = EncodeWrapper("") ):String
def lookup(tree : Tree, text: String)(implicit result: LookupWrapper[String] = LoodupWrapper("") ):String
with the obvious downside that you need to "wrap/unwrap" the String in the method body.
This could be mitigated through implicit conversion between the wrapper and wrapped types within the method, but it's still a bit clumsy, especially for very compact helper functions...
Of course everything simplifies when your method's return type is more specific and the probability for implicit collisions gets very low.
Upvotes: 0
Reputation: 35463
Have you considered supplying the implicit to lookup
explicitly in that scenario. Like so:
def encode(tree : Tree, text: String)(implicit result:String = "" ):String = {
lookup(tree, text)("other string")
}
Upvotes: 0