
Graydon Hoare on Rust 1.0.0-alpha - steveklabnik
http://graydon2.dreamwidth.org/195706.html
======
ozten
"Rust has grown to be a remarkably collective project: 559 contributors!"

The rust project is the best run open source project I've seen. The culture,
automation and communication is awesome.

~~~
iamarock
That's not my perception. For example, the language and standard library
freeze is in 3 weeks (the beta release), and yet they are doing a complete
redesign of the std::io module: [http://discuss.rust-lang.org/t/psa-io-old-
io/1403](http://discuss.rust-lang.org/t/psa-io-old-io/1403)

There's no way they could gather enough experience with the new API within
three weeks in order to commit to it for the next decades of Rust.

~~~
vhbit
And still they have enough experience with existing API to accept it is much
worse in long term perspective. With new API at least most annoying things
will be solved.

~~~
iamarock
I'm not criticizing the API overhaul, I'm criticizing the unrealistic release
schedule rush.

~~~
Animats
That's a legitimate criticism. As of yesterday, how to convert "String" to
"&str" still wasn't nailed down. (".as_string(), or "&[]"?). Things are far
better than they were a month ago, though.

After using Rust a little, I get the feeling that the borrow system, the big
innovation, is in good shape. The type system is clunky. Take a look at this
date/time module:

[https://github.com/lifthrasiir/rust-
chrono/blob/master/src/d...](https://github.com/lifthrasiir/rust-
chrono/blob/master/src/datetime.rs)

Note that none of this code does any computation. It's all field access and
update. It's not a multi-calendar system with time zone tables. This is the
code for stuffing the year into a Datetime object:

    
    
        #[inline]
        fn with_year(&self, year: i32) -> Option<DateTime<Off>> {
            self.local().with_year(year).and_then(|datetime|
            self.offset.from_local_datetime(&datetime).single())
        }
    

This has generics and a closure, neither of which ought to be necessary.
Despite all this generality, there are two copies of this code, one for time-
zone aware and one for "naive" timestamps. The author of that module has
misgivings about the structure. He writes "This is a bit verbose due to Rust's
lack of function and method overloading, but in turn we get a rich combination
of initialization methods." This is the best of the three date-time modules
available; the other two won't even compile with the current build system and
are abandoned.

There are some neat ideas in the type system. One is that if you have
something which might not be able to return a value, you have it return an
"Option<T>" value, which can have a value of type T, or a value of None.
Sorting out what was returned requires a "match" statement, which is rather
verbose. It's an elegant way to avoid null pointers and error codes, but it's
quite verbose in practice. The business with "and_then" and the closure above
is to deal with that problem. See "Option Monads in Rust"
("[http://www.hoverbear.org/2014/08/12/option-monads-in-
rust/"](http://www.hoverbear.org/2014/08/12/option-monads-in-rust/")) for an
explanation.

In Python, situations like this raise a ValueError exception. In Go,
situations like this return (uselessvalue, err). The Rust solution is formally
correct, but complex and verbose for what it's doing.

I'm worried that all this verbiage will turn new users off. It turns me off,
and I have a background in formal systems.

~~~
pcwalton
There was no need for a closure in the above code; it could have been written
with "if let" and a couple of extra lines. The use of "and_then" was to avoid
writing that extra code.

I've never once regretted the fact that Rust has no null pointers, which is
basically what you're criticizing. Null pointers cause so many bugs that the
minor effort saved by having them is in no way worth it.

~~~
Animats
The design decisions behind Rust are good ones. The ones that matter here are:

1\. Null references are undesirable. Good decision. 2\. Exceptions are
undesirable. Arguable, but not bad. 3\. There should be some way to optionally
return a null result from a function. Reasonable enough. 4\. Functional
composition is good, allowing one to write h(g(f(a))) Standard in most
languages. 5\. Object method syntax is good, allowing one to write
a.f().g().h() to compose functions. Standard in most languages. 6\. Types are
determined at compile time. Required for speed. 7\. Function overloading based
on parameter types is bad.

There are unintended consequences of these decisions. The Option<T> wrapper
type can have a value of None, which is not a type to which methods can be
applied. So, for functions that return Option, the common "a.f().g().h()" form
won't work. Workarounds are available, but they're either wordy ("'if let' and
a couple of extra lines") or obscure (using a closure as shown in the
example).

It may be better in such cases to avoid an object-oriented style, and do
composition as "h(g(f(a)))". If all the functions take Option inputs and
return Option outputs, None can be passed through the chain of functions by
having each function return None if the input is None. Because Rust doesn't
support function overloading for plain functions, the names have to be unique
within the namespace, so you can't have both "f(a: f64) => Option<f64>" and
"f(a: Option<f64>) => Option<f64>". Although some hack with
macros/metaprogramming might allow that, by creating wrappers to pass through
None.

This is getting to be a lot of machinery to do something that comes up
frequently.

~~~
steveklabnik
> The Option<T> wrapper type can have a value of None, which is not a type to
> which methods can be applied.

This is not true. I'd like you to the playpen, but it would get autokilled

    
    
        let x: Option<i32> = None;
        x.is_some();
    

h, f, and g in your examples would need to accept an Option as their
arguments, but currently don't. That's why you can't chain them together.

------
lomnakkus
A lovely sentiment, and one that I do share. If we (programmers/developers)
are to regard ourselves as professionals then we _must_ plan/design for the
fact that we will not be around forever. (In the sense that we may not be
associated with a project forever, but also that we will
eventually/accidentally/intentionally die at some point. If you _really_ care
about your profession, you'll hopefully plan for that.)

------
rjammala
Congrats! and thank you to the entire Rust team.

