Pattern matching on data contents?

63 views
Skip to first unread message

Evžen Wybitul

unread,
Oct 12, 2020, 11:55:57 AM10/12/20
to Pyret Discuss
Hey, I'm just going trough data declarations and cases and I was wondering whether there is a better way in Pyret to distinguish not only the structure of the datum, but its contents as well — similarly to how its done in Haskell. 

Take maximum. Assuming I don't want to use accumulators nor foldl1 for some reason, this could be a possible solution:

fun maximum(l :: List<Number>) -> Number:
  cases (List) l:
    | empty => raise("The list must me non-empty")
    | link(f,r) =>
      if is-empty(r):
        f
      else if f > r.first:
        maximum(link(f, r.rest))
      else:
        maximum(r)    
      end
  end
end

could be written in Haskell as:

maximum ns = 
  case ns of
    [ ] -> error("The list must me non-empty")
    [max] -> max
    (f1:(f2:r)) -> if f1 > f2 then maximum (f2:r) else maximum (f1:r)

Which matches on the list's contents directly. Is that possible to do in Pyret? (is it even desirable? Maybe it's bad practice for some reason).

Thanks,
Evžen

Evžen Wybitul

unread,
Oct 12, 2020, 11:57:55 AM10/12/20
to Pyret Discuss
Forgot to say I found a post from 2016 mentioning this pattern matching in a context of "no promises on that front". So, maybe I should ask, what's the status of this? Is/was this on the roadmap after all?

Dne pondělí 12. října 2020 v 17:55:57 UTC+2 uživatel Evžen Wybitul napsal:

Shriram Krishnamurthi

unread,
Oct 12, 2020, 1:06:10 PM10/12/20
to pyret-...@googlegroups.com
Hi. This is a controversial question (-:.

We have talked about it a few times. The problem is that the easy cases of pattern-matching are easy and welcome, but when it starts to get tricky (eg, unifying with variables), it can be very complicated. We have long felt this is too much to impose on beginners, and especially on the teachers who have to help out those beginners (who may use features the teachers don't know/understand).

If we were to have some sort of language level or macro or some other system, then one could imagine adding it as an optional feature. That's not immediately in the offing, though.

While the Pyret version you wrote is more verbose, it has the benefit of being really explicit, so there is not much doubt about what is happening. If you understand list decomposition and conditionals (which you need for most anything), everything else just follows from that.

I think it would be really interesting to conduct a user study on how beginners fare with pattern-matching: do they instinctively know what it means, or not? I expect there is some "cliff" beyond which they start to get either baffled or come to incorrect conclusions.

To be honest, I myself feel the lack of pattern-matching a little bit in two settings:
  • When teaching algorithms, where the cases depend on data (e.g., tree-balancing operations).
  • When working with pairs of data.
The latter, while it can be done with pattern-matching, could be done with a simpler extension to `cases`.

I'm curious where users on this list find pattern-matching useful or essential.

Thanks!

--
You received this message because you are subscribed to the Google Groups "Pyret Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyret-discus...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pyret-discuss/33587dfd-e0d0-48b5-83d0-ad3fcee6d6b1n%40googlegroups.com.

Evžen Wybitul

unread,
Oct 12, 2020, 5:41:44 PM10/12/20
to Pyret Discuss
I can appreciate the value of explicitness (both from a teacher and a student perspective). I took the apparent lack of haskell-like pattern matching (henceforth just patter matching) as a rational design decision and wouldn't question it, normally. But one of my students actually tried to pattern match on a list, and it didn't work, so I thought I'd ask if there isn't a way to do it after all.

> I think it would be really interesting to conduct a user study on how beginners fare with pattern-matching

The interesting thing is that the student hasn't programmed before and only saw bits of C# from his friends' homeworks. Maybe he misunderstood the way I've demonstrated the cases construct, or maybe I'd explained it badly, but nonetheless, he seemed to find pattern matching quite intuitive. Intuitive enough to be bummed when he found out Pyret doesn't support it.

> I'm curious where users on this list find pattern-matching useful or essential.

This will come as a surprise, but having "unrestricted" (i.e. pattern-matching-equipped) cases would make it simpler to explain when to use cases and when to use simple if-else. The whole "desctructuring" stuff is all nice, but the students don't really see the benefit of 

cases (List) list:
  | empty => 
    ...
  | link(first, rest) => 
    first + call(..., rest)
end

compared to

if is-empty(list):
   ...
else:
   list.first + call(..., list.rest)
end

Especially since it's shorter, familiar and just as expressive (we're not doing custom datatypes yet). The value proposition isn't good enough.

And to be honest, I'm not sure how to explain it to them. I tried the exhaustiveness argument, the explicitness argument, but... I don't think they bielive me, if you know what I mean. But that's probably my fault and not cases'.

Evžen

Dne pondělí 12. října 2020 v 19:06:10 UTC+2 uživatel Shriram Krishnamurthi napsal:
Reply all
Reply to author
Forward
0 new messages