I'm not a big fan of this. IMHO local inference is great, but it makes things so much better when function signatures are explicit.
I'm not a big fan of this. IMHO local inference is great, but it makes things so much better when function signatures are explicit.
Syntax toa apply some kind of constraint to the return type would be ok.
https://doc.rust-lang.org/edition-guide/rust-2018/trait-syst...
That has some implications for how Voldemort types work that can't be replicated with anonymous interface implementations. The main one is, Voldemort types are very thoroughly sealed. There is no way to create an instance of one outside of the function where it's defined. With an interface, anyone else could come along and create their own implementation.
- a `Box<dyn Trait>` is like a Java object referenced by an interface. Everything uses dynamic dispatch, and it is an actual concrete type (though the actual "underlying" type is type-erased).
- an `-> impl Trait` is an existential type which uses a trait as a bound, which should be equivalent to D's "Voldemort" types, except that it can still satisfy Trait requires for other functions. For example, if you `-> impl Iterator<Item = u32>`, you can pass that result to a function expecting an iterator of `u32`. However, the type is fully defined by the callee and can't be instantiated/inspected externally.
Not true in Rust, because the type returned by the function is a concrete type.
I think we may be overloading “name” here, a bit. If you return an “impl” in Rust, you have to name an interface, but you can’t actually create new instances of the concrete type returned by the function.
I think that's the distinction that really matters. The thing that's neat about Voldemort types, and gives them their interesting properties that are distinct from anonymous types, is that they have no name at all. Not even an interface or trait name.
I don't really intend to say whether they are better or worse than other ways of accomplishing similar things. Just that they're different.
Note that interfaces in Rust are not types, they do not name types. A value cannot have interface type. What happens when you return an “impl” type is that you return some unspecified type, but that type must implement the specified interface.
You could translate the D example to:
trait HasGetValue {
fn get_value(&self) -> i32;
}
fn create_voldemort_type(value: i32) -> impl HasGetValue {
...
}
The “create_voldemort_type” function simply returns a value of unspecified type. As far as I can tell, this is equivalent to the D code, except it doesn’t use type inference for the function type.(I mean this as a general statement. Idk how the language handles this)
Once the code is well defined I then start adding the type annotations , often times using the ide tooling to auto generate them.
I think a good balance would be that all published packages should have type annotations added in their source code for clarity while short scripts could do without them.
Whole form type inference is actually a super power that allows for writing extremely expressive code without giving up type safety.
However, it might be what I’m used to.
Do you think this would be less of a problem with editor/IDE support? Using colors, or other visuals, to infer and show the types while editing might overcome this desire.
With function signatures, I think it's particularly relevant for documentation as well. I should be able to look at a function signature in generated docs and know everything about what goes into and comes out of that function. For me the signature should be a complete contract, and changing code within a function body should not be able to change the signature.
Ruby, of course, technically has both as well. However, inferring a return type in a dynamically-typed language is probably less noteworthy ;)
let result = if foo > 5 {
"Big foo"
} else {
"Small foo"
};
Implicit returns are just an extension of this (it’s really just “semicolons create statements; if you don’t have a semicolon, that’s the final value of the block”). The explicit return is an actual statement that returns early.IME the holistic design works pretty well, and I think you can glue together expressions much more naturally this way. The implicit return on itself would be much more annoying IMO.