This idea is already being discussed in RFC comments here. The biggest problem with it IMHO is what happens when you want to specify a mutable reference (but it may still be the least bad option).
Thanks for pointing to that discussion! I was almost certain that It was proposed before.
I wasnât thinking about mut before, but now I see that *mut may seem misleading, as it looks like it has to something do with raw pointer. SoâŚ
We could introduce *mut operator (that would make code less ambigous but it would too much noise to consider this)
Change syntax of ref mut x to mut *x. I like it because itâs really *x being mutable, not the reference itself. (I havenât seen it being proposed in discussion)
We can also say that pattern syntax tries to mirror expression syntax and has nothing to do with type syntax. You donât use Option<x> to get value inside Some, so why should *x work for raw pointers?
Speaking of raw pointers and compatibility with C, let us remember that compatibility with C led C++ to being ugly and incosistent, so I see no reasons to pursue it. We could rename raw pointer to ^ or @ or anything, so it wonât collide with expression and pattern syntax. Itâs also worth noticing that we put * on the other side of type than C, so the original reason behind this syntax makes no sense here.
The trouble is that just as you can currently have mut ref mut x in a pattern, which results in an &mut reference to x in a mutable slot (so like let mut x: &mut T), following that logic mut *x would be an & reference in a mutable slot, rather than an &mut reference in an immutable one. I'm not sure if it's possible to support both axes of mutability any other way.
I personally wouldn't actually mind getting rid of the built-in syntax for pointer types, and replacing it with Ptr<T> and PtrMut<T>, or maybe &unsafe and &unsafe mut, or whatever. But I also wouldn't be surprised if others did. (The latter is something that I believe was actually considered at some point a long time ago and decided against, though I can't remember exactly why.)
I also came up with the same idea of replacing ref with *. Personally itâs OK to get &mut in an immutable slot with Ok(*mut ptr) => ... and to get & in a mutable slot with Ok(mut *ptr) => .... Granted, these usages of mut have nothing to do with symmetry, but I think they are no worse than the current syntax.
For me the exact opposite makes more sense. You can read mut ptr in Ok(*mut ptr) as âmutable pointerâ, and mut *ptr as âmutable value behind pointerâ. But I would be happy with either syntax, since compiler will warn/error if you get it wrong.
I find ref much more comprehensible than abusing * one more time.
Besides that I find it counter-intuitive. What is [_, *arg] supposed to mean? *arg would mean that you construct something sucht that *arg can be satisfied. It would not work like any other match. Match patterns usually reduce, ref and your proposed * increase complexity.
ref makes it more clear that it is not part of the matching pattern but just a specifier that you want a reference to the matched thing.
Itâs not ACTUALLY true, but the complicated rules for precedence and associativity of several different operators is why C declarations are confusing, not because they follow use
I donât think so. There is only one relevant precedence rule, which is that *a[b] / *a(b) are *(a[b]) and *(a(b)) respectively, not (*a)[b] or (*a)(b). Everything else about type declarations is unambiguously determined from basic syntax principles common to most programming languages.
E.g., why do you write the outer arrayâs size first, then the inner (the âassociativityâ thing Linus mentioned)? Because indexing an array of arrays (outer) gets you one array (inner), and indexing one array gives you the final element. (Some scientific languages have a specific concept of a multidimensional array distinct from an array of arrays, but C joins the norm in not.) Why int *(*x)() for a function pointer returning int *? Because int **x() would call x() and dereference the result (per that rule), while int (**x)() would dereference twice before calling. Et cetera. There is no need to remember some weird âspiral ruleâ or any other rule specific to type declarations; if you remember that one rule of precedence (which you should really know anyway if youâre doing anything with pointers), you should be able to work out any C type by following use.
But you do have to think backwards - work through what sequence of indexes, derefs, and calls you can do to x to eventually get a char, and then flip that around to get an idea of what the type looks like. I can only pin the confusion on this.
Thing is, this âthinking backwardsâ does somewhat resemble whatâs required to understand why *a would be found in a match expression.