OK, so it is the "target to argument shifting" that is weird to
    you?  That when we declare a static pattern, there is a special
    first argument that is the target ?


The sementics implies an instanceof on something which is not not visible in the syntax. People, me including, will have hard time to debug that, why this pattern is not chosen, oh, it's because of the instanceof.

Maybe I'm thick, but I'm still not seeing what's bothering you here?  Can you write out an example, and point to where the gap is, and narrate your thought process while reading the code?


    Let's not allow ourselves to be distracted by input arguments
    yet.  (I understand this adds challenges but if we're having
    trouble getting a shared understanding the base case, let's not
    jump to the general case yet.)  So I will rewrite your example as:

        Object o = ...
        switch (o) {
            case Bar$$foo(var value) -> ...
        }

    There are a series of things going on here that the user must
    understand, in order to understand this code.

    1.  Overload resolution.  The pattern Bar$$foo(var value)
    corresponds to a pattern actually declared in some code
    somewhere.  The user has to be able to reason as to how this
    pattern maps to this declared member.  This is not all that
    different from methods; when we see `foo(x)` we have to figure out
    whether this is really `this.foo(x)` in the current class, a
    static foo(x), a static-imported method foo(x), etc.  I don't
    think it's any harder for patterns, just a little different.  The
    user should be able to navigate to / find the Javadoc for Bar$$foo.

    2.  When we look at the declaration for Bar$$foo, we're going to
    see that it takes one argument and has one binding.  We're going
    to have to understand that the switch target is magically piped
    into that argument.  (For dtor/instance patterns, the same is
    true, it is just magically piped to the receiver, which is an
    invisible first argument.)

    3.  If the target type of the pattern (the type of the target
    parameter) is not total on the static type of the target (Object),
    the compiler introduces a dynamic type test before invoking the
    pattern body, and if this type test fails, the match fails and we
    move on to the next case. This is true for all kinds of patterns,
    not just static ones; the difference is how we determine the type
    of the target.

    Which of these seem problematic to you?  (Note that none of the
    above are specific to static patterns, but all are affected by
    static-ness vs instance-ness, in that we have a different way to
    declare and find the target type from a static pattern.)


        Here, I've no idea if foo takes a String, an Integer or
        whatever as first parameter, so i've no idea on which class
        the instanceof is done.


    It seems that it is #2 that is disturbing?  How is "look at the
    declaration or Javadoc of the pattern" (just like any other API
    point) not a good answer here?


Each step is reasonable but 2 + 3 is dangerous in the case the pattern references a static pattern doesn't take the current class as first parameter. Optional$$of() is ok given that it can be either an instance pattern or a static pattern but in both case, the type used by instanceof is visible.

OK, I think I finally get where you're hung up on static patterns. There are TWO types involved:

    class MumbleWidget {
        static<T>  ... pattern(T t) ... nonEmptyOptional(Optional<T> target) ...
    }

The types are MumbleWidget and Optional.  To find the pattern, the user says:

     case MumbleWidget.nonEmptyOptional(var x):

and your concern is that users will see "MumbleWidget.something" and say "Oh, this must be matching a MumbleWidget", and be confused that really it is matching an Optional?


Reply via email to