Non-exhaustive destructuring binding

I am updating some existing code to the current linting standards. One thing I encounter often is the convenience of non-exhaustive destructuring binding, like let App(Comb(f, x), y) = z. Replacing it with explicit pattern matching is more verbose, but more importantly I have to declare the variables explicitly as in let f, x, y = match z with App(Comb(f, x), y) -> f, x, y | _ -> assert false and I need to be careful matching the order in the tuples. I wonder if this is a case where the cure is worse than the disease and I should turn off the warning instead.

Anyone has an opinion on this or a better way to handle this?

[just a thought]

  1. suppress the warning at the match-site
  2. catch the match-failure somewhere further-out and convert it to a proper error-message
    ?
    In a way, it’s no worse than the rewrite you show, and i do agree that the rewrite loses meaning from the original code.
2 Likes

Some time ago I have seen a discussion (or even PR) about introducing Rust-like construction if z is App(Comb(f, x), y) then ... else .... AFAIR it was not merged because replacing it with pattern matching is not too long. You could try to find this discussion and resurrect it.

To locally disable the warning you can use

let[@warning "-partial-match"] App(Comb(f, x), y) = z

Which is not nice, but not too bad either.

(Before OCaml 4.12 you had to use [@warning "-8"] which is shorter but much less readable. To find the names for the warnings, use ocamlc -warn-help.)

4 Likes

Another possibility is disable the warnings at file level for one or several definitions. Like this:

[@@@warning "-partial-match"]

// Some code

[@@@warning "+partial-match"]

Your choice

There seem to be two different ways of dealing with this pattern. First though, @Kakadu pointed out that this subject has come up before, and was (uh) “rejected” by the OCaml community, when proposed as a syntax change ( add a `if let` construct to the language by c-cube · Pull Request #194 · ocaml/ocaml · GitHub ). I can understand why, and fend to agree with the arguments there. After all, changing the surface syntax of OCaml is a big deal.

But still, it seems like there’s a decent argument for this sort of capability, and it would seem like it’s precisely what PPX was designed for. So for instance, one could map

let%weak A(b,C d) = x in e || elsecode

to

match x with A(b,C d) -> e | _ -> elsecode

or maybe

let%nowarn A(b,C d) = x in e

to

let[@warning "-partial-match'] A(b, c d) = x in e

?

This seems like an utterly trivial PPX rewriter. Would either (or both) of these meet the need you see, @zhtprog ?

ETA: upon some reflection, the first proffered form seems bad, and maybe the “elsecode” should be moved to before the “in”, viz.

let%weak A(b,C d) = x || elsecode in e

so that one can have a sequence of such let’s.

2 Likes

This seems like an utterly trivial PPX rewriter. Would either (or both) of these meet the need you see, @zhtprog ?

Yes this seems like a really cool idea. I’d hesitate to introduce a new dependence for the existing code base but going forward it is definitely something I would look into.

Alright, so: two questions:

  1. are these proposals sufficiently clear and precise, that you think there’s no ambiguity in them? That is to say, was the (little) comment a sufficient specification?

  2. Do you think both would be nice, or just one? And if so, which one?

Also, a caution: I write PPX rewriters based on Camlp5, so if I wrote you something that solved this problem, you should think of it as an “executable specification” b/c almost certainly you’re going to want to keep using the “standard PPX rewriters from the standard ecosystem”, and not this off-the-wall weirdo rewriter from the Camlp5 ecosystem. B/c Camlp5 is incompatible with the “standard PPX rewriter ecosystem”. And no amount of “but it’s so much simpler and it’s here, not just good to have, gosh, won’t somebody implement it” should convince you to use it/depend on it, b/c that would cut you off from the mainstream of PPX development.

All that said, do you feel up to testing a prototype implementation ? With the assumption that you will not use it (for the reasons laboriously explained above) ?

P.S. I’m sorry to be so … up-front about this caution, but the last thing I want people to do, is to turn away from the standard PPX rewriter ecosystem, on my word (even partially). Life’s too short, and I like the guys who maintain the OCaml ecosystem far, far too much, to ever want to hinder their work.

@Chet_Murthy Thanks for your generous offer. Now thinking about it the second approach is not that different from using the attributes directly, which one can do without introducing ppx so it is probably not worth doing. The first approach is not safe for top level value bindings and for the following:

let A(x,y) = z
and B(c,d) = e in

I think I am good with the [@warning "-8"] (I am still on 4.10.2) for now.

Thanks again for all your help.

If-lets and more general extensions of pattern-matching were also more recently discussed here: Musings on extended pattern-matching syntaxes.

I am not sure that the scepticism about if-lets is so shared by everyone. My personal experience, being familiar with if-lets from other languages, is that you often find this feature missing for readability, for instance when it expresses in one line what currently requires three plus a pair of parentheses around the match, or when it avoids a nesting linear in the number of elses. And given that it means that any place currently accepting a boolean (if, while, when) would simply accept pattern matchings too, this does not seem to increase the language surface much (and when-lets probably increase the expressiveness). (Other extensions increase expressiveness for sure but probably cost more in terms of language complexity and design effort.)

But my perception (speaking as an outsider to this part of the language) is that for such ideas to move forward, it would require somebody brave enough to read all the discussions on this topic, summarise the debate, write a proposal that addresses all the points, and, most importantly, promises to provide a polished implementation, without any guarantee.

1 Like