The `as` operator is annoying for a number of reasons:
- the precedence is non-obvious and hard to get right (3 + 4 as uint)
- it introduces a weird ambiguity around type parameters (`3 as foo::<T>`)
Recently Go's syntax was proposed as a remedy (`3.(int)`), but rejected
because it looked weird (which it does).
But it occurs to me that we don't really use `as` for much. In fact, we
use it for three things: converting between numeric forms, creating
boxed ifaces, and converting C-like enums to their integer values. I
have good alternative forms for the first two, not sure about the third.
### Converting between numeric forms
We can simply create some impls for the appropriate conversions. For
example:
```
impl conv_methods for int {
fn uint() -> uint { sys::int_to_uint(self) }
fn u32() -> u32 { unsafe::reinterpret_cast(self) }
fn float() -> float { ... }
}
```
These have the advantage of clear precedence and they're more attractive
to boot (at least to me). Examples:
- `3.uint() + 4u`
- `(3+4).uint()`
### Creating boxed ifaces
I've started to find it a bit odd to use `as` to create a boxed iface,
since `as` looks like a "bitcast" (in LLVM terms) but it's actually
performing allocation. It's also quite repetitive, especially if the
iface has type parameters. Therefore, I propose we simply use the
`iface` keyword to indicate "create a boxed iface". So, instead of this:
foo as my_iface::<T1,T2>
we would write
iface(foo)
The required iface and type parameters would typically be inferred from
context, but if you wanted to make it fully explicit, you would do:
iface::<my_iface<T1,T2>>(foo)
This purposefully resembles a method call but of course `iface` is a
keyword so it is not, in fact, a method call but rather a special form.
*An aside:* I originally thought to use the name of the iface as the
constructor for a boxed iface (e.g., `my_iface(foo)`) but I eventually
rejected it because if we move to a system where ifaces can be allocated
not only in `@` boxes but also on the stack and so forth, the `iface`
keyword should be easily extensible to this scenario, whereas
`my_iface(foo)` is not. This is true regardless of whether we use
"suffixed types" (e.g., `iface@(foo)`, `iface~(foo)`) or move to a
prefix-with-dynamically-sized-types system (e.g., `@iface(foo)`,
`~iface(foo)`). Neither case can be gracefully handled by a named
constructor function unless these functions are actually treated
specially by the system.
### Converting C-like enums to their discriminant
Actually, I don't have a good idea what to do here. The compiler could
of course automatically define the relevant methods on C-like enums
(`int`, `uint` and so on) but that seems hokey.
Thoughts?
Niko
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev