roc-lang / roc

A fast, friendly, functional language.
https://roc-lang.org
Universal Permissive License v1.0
4.49k stars 315 forks source link

Need to be able to default destructured values that are renamed. #6532

Open B-Teague opened 9 months ago

B-Teague commented 9 months ago

I came across a scenario where I needed to destructure multiple instances of a record: point1 and point2 that had an optional z coordinate for 3 dimensions. Please see example below

Point a : { x: Frac a, y: Frac a, z ? Frac a }

distanceBetweenPoints : Point a, Point a -> Frac a
distanceBetweenPoints = \point1, point2 ->
    { x: x1, y: y1, z: z1 ? 0.0 } = point1
    { x: x2, y: y2, z: z2 ? 0.0 } = point2
    Num.sqrt (
            Num.pow (x2 - x1) 2.0 +
            Num.pow (y2 - y1) 2.0 +
            Num.pow (z2 - z1) 2.0
    )
── RECORD PARSE PROBLEM in main.roc ────────────────────────────────────────────

I am partway through parsing a record, but I got stuck here:

14│      {x:x1, y:y1, z: z1 ? 0.0} = p1
roboteng commented 9 months ago

I was curious and looked into this a bit. It looks like the line { x: x1, y: y1, z ? 0.0 } = point1 can compile, but the line { x: x1, y: y1, z: z2 ? 0.0 } = point1 doesn't compile. It seems the root cause that you can't combine the optional record field with the renaming, both of which are needed here.

roboteng commented 7 months ago

Until this is solved, I found this workaround:

distanceBetweenPoints : Point a, Point a -> Frac a
distanceBetweenPoints = \point1, point2 ->
    { x: x1, y: y1, z: z1 } =
        { x, y, z ? 0.0 } = point1
        { x, y, z }

    { x: x2, y: y2, z: z2 } =
        { x, y, z ? 0.0 } = point2
        { x, y, z }

    Num.sqrt
        (
            Num.pow (x2 - x1) 2.0 +
            Num.pow (y2 - y1) 2.0 +
            Num.pow (z2 - z1) 2.0
        )