No dollars for you

The warning about dollars in X$Y identifiers got bumped to 3.9, so naturally I recommend

-source:3.9

This was a case of “it would be nice to warn (for beginners and others who may be unaware) if it’s not annoying”. So it warns only about definitions, not references, and the easy escape hatch is the trusty backquote, which is to Scala 3 what the underscore was to Scala 2, namely, “your friend when you just don’t care”.

During recent contributions, I realized that I especially don’t like proposing something unintelligent or suboptimal. That is not merely because of some inner sense of value in computing, but because the smart reviewer will tell me so.

My previous gauge or grid was on the order of, I wouldn’t mind learning something about that, how much time am I willing to contribute to a) learn something and b) fix something. Usually I’m starting from, Gee, I don’t know anything about that; although there are a few topics where I begin with, That bug is probably my fault.

However, there is a quick degradation where an “adequate” fix is worth an hour, but a “highly polished, gleaming spit-shine” fix that requires another hour is not terribly worth it.

I don’t know how Claude manages this phase change; I have not asked, but maybe someone has. Does anyone prompt Claude to reduce code duplication until you are bored with this task?

I try not to insist that a given edit is useful (though usually I think so, because otherwise why would my fingers, which don’t need the exercise, have typed it in? unless I was in a sort of trance, receiving instructions from some disembodied intelligence without being aware of it).

During a code review, I am especially open to suggestions about runtime overhead and code complexity (either that I have introduced it or how to reduce it). I think that is because people get mad when software is slow, and also when they have to read it.

I don’t know if warning about dollars is worth any cycles, but I see that I accidentally added it up-front in namer, instead of relegating it to a later linting phase. Oh, that may be because the original idea was that this would be a hard error. I’ll try to follow up with an “improvement”.

Mostly I try not to make things worse (the developer experience, the maintainer experience, the researcher experience), if the improvement is marginal. I did not submit a paper for “No dollars for you!”, despite the punning opportunities on the fate of the greenback in the current political environment.

I hope we are close to getting an initial review from the indefatigable sjrd-bot, so that remaining issues after the first-round review would pertain to architecture or feature choices. I know that a second review from odersky-bot would have told me to move all linting way past typer.

Edit: I forgot to note that this is the last time I contribute a new “error ID” without support from Claude. What was a maintenance nuisance is now beyond the intervention of those – what are the epithets? wet-ware? meat-bags? – for whom awesome messages were devised. Or should awesome messages be re-architected to appeal to A.I. who will both produce them and consume them?

1 Like

I wonder if it is surprising that these are not the same:

    val start @ _: String = ""
    val start @ (_: String) = ""

I mean it is surprising to me, but I wonder if it is also to others, to whose secret thoughts I am not privy.

The second form corresponds in Scala 2 to val start: String, but in Scala 3 it preserves its shape.

The first form is not legal!

Now it will tell you so, unless some further dispensation is granted:

2 |val start @ _: String = ""
  |    ^^^^^^^^^
  |Type ascriptions after patterns other than:
  |  * variable pattern, e.g. `case x: String =>`
  |  * number literal pattern, e.g. `case 10.5: Double =>`
  |are no longer supported. Remove the type ascription or move it to a separate variable pattern.

I was led down this garden path, which meanders East of Eden, when I realized I had no idea what this type ascription means:

val (a, b, c: Double): (Int, String, Double) = ((42, "hello, world", 3.14): Any).runtimeChecked

I had no idea beyond a couple of reasonable guesses.

The issue of the day was that we support

case `type`: Int =>

but balk at

case T: Int =>

which must be written

case T @ (_: Int) =>

I will propose just accepting the form that looks like val T: Int since it cannot be a stable identifier pattern. Currently it warns, where Scala 2 errors that a pattern variable must be lowercase. We may call the typed pattern a pattern definition to distinguish it from other uses of pattern variables.