Pattern matching vs function application

In functional programming it is frequently suggested to use pattern matching as it gives a more intuitive description of what the operation is doing.

For example, the addPoints function that adds three dimension points is traditional written to pattern match the individual dimensions of the point like this:

addPoints : (Decimal, Decimal, Decimal) -> (Decimal, Decimal, Decimal) -> (Decimal, Decimal, Decimal)
addPoints (a,b,c) (x,y,z) = (a+x, b+y, c+z)

as opposed to something like

addPoints : (Decimal, Decimal, Decimal) -> (Decimal, Decimal, Decimal) -> (Decimal, Decimal, Decimal)
addPoints p1 p2 = (p1._1 + p2._1, p1._2 + p2._2, p1._3 + p2._3)

or even

addPoints : (Decimal, Decimal, Decimal) -> (Decimal, Decimal, Decimal) -> (Decimal, Decimal, Decimal)
addPoints p1 p2 = (fst3 p1 + fst3 p2, snd3 p1 + snd3 p2, thd3 p1 + thd3 p2)
  1. Do we still make that recommendation in Daml?
  2. For those on the fence about the clarity of pattern matching. Are there performance implications for one style over the other? Both fst3 and the “_1” syntax are function calls so do they incur an extra penalty?

I’d still make that recommendation in Daml although both in Daml and in other languages, I think the more strong recommendation is wrt to variants not with records. In particular, you want to avoid things like

if isSome x then doSomething (fromSome x) else …

For records, I usually default to pattern matching if I need all fields but in some cases when you only need one field and you only need it once, record selectors make more sense.

In your example, there is no meaningful difference in performance. They compile to comparable even if not quite identical code.

In general, there can be a difference though. The first version will only evaluate each record selector once whereas in the second version if you use something like p1._1 multiple times it will get evaluated multiple times.

For this kind of code I’d recommend the first one, but with types:

data Point = Point { x: Decimal, y: Decimal, z: Decimal}

addPoints : Point -> Point -> Point
addPoints (Point x1 y1 z1) (Point x2 y2 z2) =
  Point (x1 + x2) (y1 + y2) (z1 + z2)