I’ve always wanted one in a language I’d have some reason to use, ever since learning Pascal as a kid. I think they’re less ambiguous, and thus easier to work with. With C you can use [0], which is kind of a poor-man’s postfix dereferencing operator… But in Rust, it seems you have to resort to parentheses to deal with the ambiguity? Consider this program, demonstrating the ambiguity:
use std::ops::Deref;
struct Foo(Bar);
struct Bar(Baz);
struct Baz;
impl Deref for Foo {
type Target = Bar;
fn deref<'a>(&'a self) -> &'a Bar {
println!("Deref Foo");
&self.0
}
}
impl Deref for Bar {
type Target = Baz;
fn deref<'a>(&'a self) -> &'a Baz {
println!("deref Bar");
&self.0
}
}
fn main() {
let x = Foo(Bar(Baz));
let _ = *x;
let _ = *x.0;
let _ = (*x).0;
}
On the other hand, the ambiguity would be removed with a postfix dereferencing operator:
fn main() {
let x = Foo(Bar(Baz));
let _ = x*;
let _ = x.0*;
let _ = x*.0;
}
(aside: I know this would allow a syntactic ambiguity on something like x.0 * 3… it’s the same ambiguity that currently exists on 3 * x.0, just with the terms reversed.)
I know this won’t happen at this point, but it would have been nice…
I may be mistaken, but I think the ambiguity issue with the prefix operator is less severe than with postfix?
Postfix:
foo*(1+2)
Now is this multiplying foo by (1+2), or dereferencing foo and then function-calling the result with 1+2?
Prefix:
(1+2)*foo
does not have the possibility of being a function call.
I think a postfix dereferencing operator (if we continue to use * for it, which we also use for infix multiplication) would have to require whitespace-sensitive syntax, but I think those are both good ideas and plan to use them if I ever design a language myself.
Actually, neither of those are ambiguous. x.0 * 3 still only has one valid parse. It's just that x.0 * 3 requires more lookahead than 3 * x.0. The current 3 * x.0 case only requires one token of lookahead for the operator itself. While your x.0 * 3 requires infinite lookahead, since it has to keep looking ahead until it finds a token that starts a primary expression or ends statement. To demonstrate, x.0***; is 3 derefs, x.0***3 is 2 derefs and a multiplication.
It doesn’t look like that requires infinite lookahead? x.0***3 looks like it requires only one token of look-ahead. At the first *, look ahead one, see another *, then the first token must be a unary deref while the second token is undetermined… By the time the parser reaches the 3, the first two *'s have already been resolved to unary deref expressions, right?