Mini-SIP for case if

I have posted a mini-SIP to permit

case if p =>

instead of

case _ if p =>

Folks might be ready with a spray can of bike shed color.

It’s also possible you’d like me to push this crazy scheme even further.

I’m going to voice a :-1: on this one.

To me this is just a special case for the sake of a special case. It’s one more thing to learn, for no obvious reason, other than “the alternative is ugly” (which is subjective, IMO it’s quite fine). I can almost hear the developers confused by "what is the difference between case _ if and case if.

If we compare to another seemingly innocuous syntax SIP that made it, i.e., trailing commas, at least there were some technical advantages to the new syntax (diffs when adding/removing lines in varargs). I don’t see anything like that here.

11 Likes

I hear that as a call to push the scheme even further.

That is, the SIP can be renamed “underscoreless”, and underscore should be eliminated where extraneous.

42 match {
  case n if n >= 42 =>
  case =>
}

The currently broken semantics for val should be fixed to represent “fresh name”:

implicit val _ = concurrent.ExecutionContext.global
implicit val _ = 42

We reached this tipping point already when s"$_" syntax was disallowed for placeholder syntax in interpolated expressions.

An underscore would be useful for case only to express:

t match {
  case implicit _ => implicitly[T]
}

if that syntax were admitted.

The technical advantage to eliminating the extraneous underscore is that the line is textually shorter. This matters because folks enforce maximum line lengths. The citation in the SIP is a maximum line length of only 100 characters. The hardest problem in CS is not naming, but coming up with names that satisfy the line length enforced by checkstyle or scalastyle or pernicious code reviews.

Although one can dispute regularity of syntax, I don’t think one can deny, on the face of it, that case _ syntax suffers the specific disadvantage of verbosity as outlined in the SIP.

Hmm. At least tentatively, I agree with @sjrd on this one. Yes, it’s a little more concise, but two characters isn’t enough for me to find it really compelling. And I do find it a bit unintuitive, at least at first look.

That underscore is pretty easy to explain when I’m teaching: “you use underscore to say ‘I don’t care about the specific name/value that goes here’” – it’s consistent enough that folks tend to pick it up pretty easily. Unless this underscoreless syntax can be made to work more or less consistently around the language (which I’m skeptical about, although open to being convinced), I think it makes it harder to understand…

2 Likes

@som-snytt If you intend to incorporate those changes into the SIP, I encourage you to update the official proposal in the website.

Personally, I must say I don’t think this is a good idea. I agree with @jducoeur that I find it even difficult to read. At least the _ can be predicted and it’s consistent with the current syntax.

Let me know when you’re ready with the PR so that I can kick off a voting to number this proposal.

I’m also against the case if proposal, but strongly for the implicit val _ = ... proposal. Though it’s 2018 and those implicits should have types, which requires implicit val _ : Foo = ..., with a crucial space between the underscore and the colon. Unless we’re going to change the parsing rules too…?

I just saw the proposal for _ meaning a fresh name. It’s always been confusing to me that _ doesn’t have this behaviour by default. I think it would be a nice addition to make it conform to the fresh name semantics and that you’re allowed to define as many val _ as you want in the same scope.

3 Likes

@jvican Great! The one thing which concerns me, though, is the parsing of adjacent _s and :s. Total bikeshedding issue…

While I love the idea of no longer having to come up with names for my implicits, other people (especially @sjrd I think) have argued elsewhere that this is bad for binary compatibility unless it’s restricted to local values.

1 Like

You shouldn’t be allowed to declare a public member without an explicit name. Private should be fine.

Oh, I’m perfectly fine with this restriction being lifted for everything but local values but note that it’s kind of orthogonal to whether val _ generates fresh names or not.

1 Like

If the freshname were derived from the type of the implicit there would be less of a binary compatibility problem, by virtue of uniqueness of implicits. IIRC, elsewhere it was discussed (implemented?) that name-based shadowing of implicits should be removed from the language, which I think would be a prerequisite of basing the freshname on the type (otherwise accidential shadowing would be too risky).

Thanks, I will update with the hard-core version when I have a moment. (That is, _ is not an Expr1 so it’s not a Pattern1 either, or something like that of persuasive symmetry.)