Does Scala provide a way to make an anonymous val?

2019-08-15 04:45发布

问题:

Can you make an anonymous val?

I'm thinking to do something like this:

case class NumIterations[A](num: Int)
case class Seed[A](seed: A)
case class Manipulate[A](f: A => A)
. . .

def funcWithGobsOfImplicitArgs[A](
  implicit numIterations: NumIterations[A],
           seed: Seed[A],
           manipulate: Manipulate[A],
           . . .
): A = . . .

def apply(): String = {
  implicit val NumIterations[String](10)  // This is where I want anonymous vals
  implicit val Seed("xyz")
  . . . 
  funcWithGobsOfImplicitArgs
}

Okay, making all of the function's arguments implicit is probably going overboard, but I do have a real application where it's handy to stick some function parameters in scope and then re-use and override them. This makes experimenting with the function very convenient. I can play with one parameter at a time explicitly and let all the others be supplied implicitly.

In this situation, it would be nice not to name the val, since the name takes up space in your head, and the full meaning of the val is provided by its type alone. When I only had one of these vals, I named it _, thinking that Scala would treat it as a val that never gets referred to explicitly. But when I named two vals _, Scala complained.

回答1:

No, you need to name your val. Generally I think your idea makes the code really hard to maintain and understand. If in a context, I have two functions both have an integer implicit parameter which the conceptual meaning of these two parameter are completely different, I will define two different value classes and change my function argument type to these value classes, so now I will define two different vals of type these value classes in the context.

class Arg1(arg: Int) extends AnyVal
class Arg2(arg: Int) extends AnyVal
def f1(implicit arg: Arg1)
def f2(implicit arg: Arg2)
implicit val arg1 = new Arg1(1)
implicit val arg2 = new Arg2(2)
f1 // will pick arg1
f2 // will pick arg2

But if the conceptual meaning of the arguments are the same (like ExecutionContext for example), then I name it executionContext and define it as an implicit in the context, so all the function requiring that argument will use that.