Though I don't see why usefulness of the feature in a low-level libraries should be the warning sign.

I don't dispute it's usefulness, but I'm sure you agree that "usefulness > 0" is not the bar for putting a feature in the language -- it is way, way higher than that.

My bigger concern is that it is error-prone -- especially if we release type-test patterns and Class constant patterns at the same time.  Many users will be tempted to use Class patterns as a less ugly alternative to instanceof tests -- and then their code will be subtly wrong.  When given the choice of what looks like "old fashioned switch with a new type", and "new-fangled type-test patterns", many users will lean towards the former because its familiar.  And get the wrong thing.

So the problem is not that its only useful to low-level users; its that others users may be tempted to use it, and get the wrong thing.  (This isn't theoretical.  "Type Switch" has been an RFE for years; in the examples presented as justification for the feature, many wrongly conflate it with instanceof.)

In any case I'm pretty sure that switch on class will be more applicable, than the switch on floats. But you are doing theswitch on floats. Why? For consistency, of course. You want to support all literals in switch. But class literals are also literals, according to JLS 15.8.2, so it is inconsistent not to support them (especially taking into account that their usefulness is not the lowest of all possible literals).

"For consistency" arguments are always weak justifications for including a feature, because you can always find a precedent or rule to be consistent with.  The justification is not merely for consistency; it is to avoid introducing _new_ asymmetries.  It would be silly to not allow float literals as patterns; then you couldn't match against `Complex(0.0f, 0.0f)`.

So the choice is not about float in _switch_, but about float as a _pattern_.  Once you admit the latter, it is hard to say no to the former.  (Same with null; we're not doing `case null` for its own sake, its to support `null` as a pattern; using it in `case` is a consequence of that.)

So, should class literals be a pattern?  That would also mean that you could say

    if (x instanceof Foo.class) { ... }

and it would mean something subtly different than

    if (x instanceof Foo) { ... }

That's not so good.  Or the same mistake in switch:

    switch (anObject) {
        case "Foo":
        case String.class:
        ...
    }

which means "does anObject equal the constant String.class".  The confusion between `String` and `String.class` as patterns is a pretty serious risk.  And again, introducing both kinds of patterns at once makes it worse.

So, while I think its a consistent and useful feature, I also don't think its a necessarily good idea to expose everyone to this confusion.


Reply via email to