I recently came across a odd syntax in Scala that I've never seen before and there seems to be no mention of it anywhere in Scala docs. I have a suspicion that this is just an odd way to name a method, but wanted to check if it's not something else.
class Reader(props: PropertyResolver, prefix: Option[String] = None {
def $$[T](name: String)(implicit conv: String => T): T => props.$[T](prefix.fold(name)(_ + name))
}
Just a general wondering whether I understand correctly that somebody was crazy enough to call method $$
Why it works
Despite violating naming conventions,
$$is a valid method identifier. It's ordinary even by JVM's standards, i.e. it does not require any Scala-specific name mangling (the dollar sign$is a valid identifier name in Java). This is all valid Java (bad, but valid):It's in no way specific to the JVM either. JavaScript's jQuery has been doing this for decades. This is valid JS code:
and allows you to do these typical jQuery-style-selections, as in
Why you shouldn't do it
While the JVM doesn't care and works with
$s in identifiers just fine, in the actual programming languages (Scala, Java), the usage of$in identifiers is strongly discouraged, because your identifiers might inadvertently collide with synthetic identifiers generated by the compilers. For example, this Java program:does not actually compile, because our manually defined
Dollarz$Aclass collides with the synthetic name that thejavacgenerates for the nested classA.Similarly, for Scala, the following code snippet:
produces a strange error message
Dollarz is already defined as class Dollarz in Dollarz.scala, despiteclass Dollarz$andobject Dollarzcompiling just fine on their own. The problem this time is thatscalactries to generate a synthetic classDollarz$for the companion objectDollarz, which then ends up colliding with the already defined classDollarz$.Moreover: even if your code with
$-characters in identifiers compiles now, the backward compatibility is not guaranteed, i.e. you should treat all names with$s as reserved by the compiler designers. If in Scala 3.45 someone decides to generate bunch of synthetic methods$$,$$1,$$2... on every class, and your code breaks because of the collisions, then it will be your fault. The Spec explicitly tells you not to use it in user programs: