scala - Using an implicit parameter in a recursive function -
consider following hypothetical binary tree traversal code:
def visitall(node: node, visited: set[node]): unit = { val newvisited = visited + node if (visited contains node) throw new runtimeexception("cyclic tree definition") else if (node.hasleft) visitall(node.left, newvisited) else if (node.hasright) visitall(node.right, newvisited) else () }
i reduce duplication making visited
parameter implicit, so:
def visitall(node: node)(implicit visited: set[node]): unit = { implicit val newvisited = visited + node if (visited contains node) throw new runtimeexception("cyclic tree definition") else if (node.hasleft) visitall(node.left) // newvisited passed implicitly else if (node.hasright) visitall(node.right) // newvisited passed implicitly else () }
however, gives following compile error:
ambiguous implicit values: both value
visited
of typeset[node]
, valuenewvisited
of typescala.collection.immutable.set[node]
match expected typeset[node]
is there way can tell compiler "expect" implicit value visited
parameter, not use implicit value when recursively invoking method?
unfortunatelly there no annotation-based solution, (@nopropagate implicit visited: set[node])
, have shadow it:
scala> def visitall(node: node)(implicit visited: set[node]): unit = { | implicit val visited = set[node]() | visitall(node) | } visitall: (node: node)(implicit visited: set[node])unit
however, doesn't work if want access shadowed value:
scala> def visitall(node: node)(implicit visited: set[node]): unit = { | val unshadowed: set[node] = visited | implicit val visited: set[node] = unshadowed | visitall(node) | } <console>:10: error: forward reference extends on definition of value unshadow ed val unshadowed: set[node] = visited ^
so, may (checked repl) then:
def visitall(node: node)(implicit visited: set[node]): unit = { val newvisited = visited + node ;{ implicit val visited = newvisited if (visited contains node) throw new runtimeexception("cyclic tree definition") else if (node.hasleft) visitall(node.left) // newvisited passed implicitly else if (node.hasright) visitall(node.right) // newvisited passed implicitly else () } }
or this:
def visitall(node: node)(implicit visited: set[node]): unit = { ({implicit visited: set[node] => if (visited contains node) throw new runtimeexception("cyclic tree definition") else if (node.hasleft) visitall(node.left) // newvisited passed implicitly else if (node.hasright) visitall(node.right) // newvisited passed implicitly else () })(visited + node) }
the idea move shadowed implicit inside nested block of code
Comments
Post a Comment