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

Reply via email to