Repository navigation
RFC: Allow matching against n-ary variants with just the name #1701
Description
Activity
Haskell does something like
Foo{}to mean "match onFooand I don't care how many arguments it has". The exact syntax doesn't matter, but it seems like distinguishing that case from the case whereFoois nullary might make the implementation a little simpler.The implementation is already trivial even without extra syntax -- in fact, I think it'd mostly be a matter of removing the check that currently causes the error.
I like the idea of making this case easier, but I think using the same syntax as nullary variants could make refactoring very difficult in one situation. Right now every time you change a tag you can lean on the compiler to tell you everything you need to update. Giving both these scenarios the same syntax will mean the compiler can't distinguish between the 'I believe this is a nullary variant' and 'I don't care how many arguments this variant has' cases. So promoting a variant from 0 arguments to some arguments gets you no feedback from the compiler.
But what is the situation where this might actually introduce a bug? If you
add a new arg to a variant, presumably existing code matching it doesn't
need this value. There are cases where it does, but you can't protect the
user from all refactoring problems (they could also change arg order,
rename something, etc, which is easily more dangerous).What if you change a variant from nullary to unary? It's possible that code might have to treat values constructed with that constructor differently depending on the value of the field.
It's true that we can't protect the user from all refactoring hazards, but to me that doesn't seem like a very good argument for disregarding any particular hazard. Obviously, there are some we'll address and some we won't, but the fact that there'll be some that we won't doesn't provide any help in choosing which ones to address.
A) Extra syntax is also a cost.
B) The idea to distinguish nullary from n-ary doesn't even solve the (theoretical) problem. You'd still have the same issue adding an argument to a tag that already had arguments—the existing cases that match 'this variant with any arguments' would keep on matching.
But that is exactly the point of this proposal. To reduce needless coupling. If coupling is something you guys consider a good thing, then we're just arguing from completely different standpoints.
I'd tend to agree with Tim — sometimes coupling is good because it helps refactoring, and sometimes it's a nuisance. Depends on the situation, I think.
I like the idea of having a pattern (maybe
foo _, distinct fromfoo(_)orfoo), that means "just match againstfoo, I don't care how many arguments it has—or even if it's nullary or n-ary".How about
name*(rather thanname _)? I like the way it looks slightly more.I think this would be great. I was going to propose the syntax
name(*)orname(_*)but I see there are many other proposals... I don't really care but I think @marijnh is right that we need something like this. It's very annoying to refactor otherwise.foo(...)perhaps?I personally like
foo(...).It is my understanding that
...is already claimed by the macro system, in pretty much every syntactic context.It seems like there is consensus that we should implement this, and it's just down to choosing the syntax. I volunteer to do it -- I favor
name(*)as suggested by @nikomatsakis but if you object, comment soon.I've implemented the new syntax, but going through and using it is still a separate task (probably easiest to do it incrementally, or I suppose someone could do an automated search-and-replace).
There's lot of stuff like this in the current code:
Where we need to have the
(_, _, _)in there even though we just want to match a variant, and don't care about the arguments. If I understand correctly, we're already disallowing shadowing such variants in patterns, so it is probably a good idea to also allow matching against them with just their name. I.e.