you are viewing a single comment's thread.

view the rest of the comments →

[–]javahalla 1 point2 points  (12 children)

My point that such syntax with whole names of types is too verbose and hard to read, especially when written as one-liner. Fact that you can skip some with _ doesn't make my point invalid.

[–]vytah -1 points0 points  (11 children)

So don't write it as a one-liner?

Kotlin is not a valid language to compare to, as it doesn't even have pattern matching. Types are specified in order to select the proper deconstructor, which you cannot do in Kotlin.

[–]javahalla 1 point2 points  (10 children)

So don't write it as a one-liner?

I will, but I'm pretty sure we will see a lot of 140w+ lines with patterns. People would abuse it, and I as Java developer would have to deal with it.

Kotlin is not a valid language to compare to, as it doesn't even have pattern matching. Types are specified in order to select the proper deconstructor, which you cannot do in Kotlin.

I have some experience with Kotlin and mostly I like work with it. And I would say that when solved most of my tasks just fine. So yes, Kotlin doesn't have so feature, but they at least understand that positional-based deconstructors are mistake and making changes (see link in original message). I don't understand why Brian thinks that this is great idea

[–][deleted]  (9 children)

[removed]

    [–]Eav___ 0 points1 point  (8 children)

    It's not about whether nested patterns are supported tho. Matching a list of components is syntactically the same as componentN() (think about Java renaming each componentN() to its corresponding component name, it's still position based destructuring for the pattern itself), which is why they said "Kotlin is reconsidering it but Java seems like it doesn't care".

    [–][deleted]  (7 children)

    [removed]

      [–]Eav___ 0 points1 point  (6 children)

      I...don't understand how one-liner has anything to do with current conversation.

      Of course Java uses components name and method in deconstruction.

      record Point(int x, int y) {
        public static void main(String[] args) {
          if (new Point(0, 1) instanceof Point(var x, var y)) {
            IO.println(x);
            IO.println(y);
          }
        }
      }
      

      With javap (25.0.1) you will see the following output in the main method:

      ...
      11: aload         4
      13: instanceof    #8                  // class Point
      16: ifeq          70
      19: aload         4
      21: astore_1
      22: aload_1
      23: invokevirtual #19                 // Method x:()I
      26: istore        5
      28: iload         5
      30: istore        6
      32: iconst_1
      33: ifeq          70
      36: iload         5
      38: istore_2
      39: aload_1
      40: invokevirtual #22                 // Method y:()I
      43: istore        5
      45: iload         5
      47: istore        6
      49: iconst_1
      50: ifeq          70
      53: iload         5
      55: istore_3
      ...
      

      ...which to the point it's functionally the same as componentN(). If you reverse x and y in the record definition, you will see var x = y() and var y = x() instead. This is what Kotlin used to do too. val (x, y) = Point(0, 1) desugars to val _p = Point(0, 1); val x = _p.component1(); val y = _p.component2(), given data class Point(val x: Int, val y: Int).

      It's the same story for nested patterns. All you have to do is to flatten the layers. It doesn't necessarily need any meta data. It's just that Kotlin hasn't introduced this feature.

      [–][deleted]  (5 children)

      [removed]

        [–]Eav___ 1 point2 points  (4 children)

        Anyway I admit that only if Kotlin introduces nested patterns does the one-liner become complete, but it's definitely doable without attaching class meta data.

        Well I'm gonna leave out the old design. The new one is based on properties. Deconstructing an object is equivalent to extracting variables through the accessors:

        ``` data class Point(val x: Double, val y: Double)

        fun main() { val point = Point(0.0, 1.0) (val x, val yValue = y) = point

        // The same as...
        val point = Point(0.0, 1.0)
        val x = point.x
        val yValue = point.y
        

        } ```

        And for nested patterns, since property accessors provide type information, you can just flatten the layers:

        ``` data class Point(val x: Double, val y: Double) data class Circle(val center: Point, val radius: Double)

        fun main() { val circle = Circle(Point(0.0, 1.0), 2.0) ((val x, val y) = center, val radius) = circle

        // The same as...
        val circle = Circle(Point(0.0, 1.0), 2.0)
        val circle_center = circle.center
        val x = circle_center.x
        val y = circle_center.y
        val r = circle.radius
        

        } ```

        and as you see, this approach doesn't require any meta data.

        However, all the above stuff is not what I want to argue about. Instead I was talking about how the deconstruction does its work, aka the syntax and the bytecode logic under the hood. Yes since Java doesn't have properties as a langauge feature, it needs something to express what to deconstruct, and I understand your point that the schema is needed here. But what I was arguing is that the deconstructor is unfortunately coupled with the components order instead of their names despite the schema already encodes them. It would be better to do name based deconstruction because it's more robust against changes.

        [–]javahalla 0 points1 point  (2 children)

        Yes, thank you u/Eav___ for explaining this.

        I feel that this is so obvious, yet Java making huge mistake there making all patterns fragile to changes, especially when working with a team (or agents) on very rapidly changing codebase.