Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I don't know, that is the kind of comment you used to hear from LISP programmers about how their program was really an elegant mathematical proof of its own correctness.

That's great until you try to do some real world things with it and run into endless impedance mismatches.

Rust isn't quite so far up its own butt, however the developer community doesn't seem to realize that there's a massive gap between the toy example programs in their documentation and the level of knowledge needed to build something worthwhile.



> the developer community doesn't seem to realize that there's a massive gap between the toy example programs in their documentation and the level of knowledge needed to build something worthwhile.

I don't think Servo and rustc itself are "toy example programs".


Are Servo and rustc in the Rust documentation? Literate programming of some sort? Maybe you're replying to a different criticism.

I've been through the Rust Documentation (doc.rust-lang.org) and Rust By Example (rustbyexample.com) several times now, and I have to jump on IRC to get answers to (what I think should be) some pretty simple questions.


If you think something important is missing from the docs, please open an issue. Steve Klabnik is very keen on making the documentation as useful as possible.


Steve seems like a genuinely helpful guy, but I'm not sure my most recent headache is a documentation problem so much as a deficiency in the std/core library. I was trying to write a generic function that called abs() on some of the arguments. Here's a simplified version:

    fn simplified_example<T>(a: T, b: T) -> T
        where T: Copy + PartialOrd
    {
        if a.abs() < b.abs() {
            // some irrelevant math goes here
        } else {
            // slightly different math goes here
        }
    }
I'd like to be able to call this generic function on anything that has a .abs() method. That includes i8, i16, i32, i64, f32, f64, and so on. Is that a shortcoming in documentation or an unfortunate consequence of Abs not being a trait? Several people on IRC recommended the rust-num/num crate, but that has several other deficiencies, and I don't think I should need another crate (unwanted dependency) to call .abs() on f32 or f64. With help, I came up with a workaround, but this was harder than I think it should be.

The grandparent poster said:

>> the developer community doesn't seem to realize that there's a massive gap between the toy example programs in their documentation and the level of knowledge needed to build something worthwhile.

I have to agree with him. The level of Rust-specific knowledge required to get the absolute value of a number/type in a generic function is pretty significant. The example above is just a small part of a library I'm working on and only one example.


We tried to get a trait hierarchy for numerical right four or five times; it's really hard. So yeah, you have to use num or make your own at the moment. It's true this is less than optimal; it's just not an easy problem. For just abs it should only be a few lines of code to make your own; three for the trait, and five times two for the impls.


> We tried to get a trait hierarchy for numerical right four or five times; it's really hard.

I'm clearly not an expert in Rust, and as such I realize my opinion isn't worth much, but it seems to me any attempt to build a numerical hierarchy will result in something fragile. Scheme has a well thought out minimal hierarchy, and even without all the complexity from all the fixed sizes I don't like theirs either. However, it's alright because they have dynamic typing as a release valve. C++ templates dodge the problem because they act more like duck typing, and I think I understand why Rust won't go that way.

Instead, I think you should abandon the goal of trying to create a hierarchy and just treat each small concept as a trait. Rather than creating Signed for things with a sign, and Float for things that are floating point and so on as in the num crate, create Abs as a small concept in its own. Then anything on which you can call .abs() implements the Abs trait. This includes things which aren't "signed", such as unsigned numbers and complex numbers - all of those have a useful (even if sometimes trivial) definition of .abs()

Trying to build a hierarchy reminds me of the stereotypical examples of bad object oriented design - I'm sure you know the cliches where Human derives from Ape, then Mammal, then Animal, etc... A hierarchy is like trying to build a directory tree, but numeric traits are more like labels on your gmail messages. Traits seem more like mixins or interfaces.

You'll end up with a lot of one or two method traits, but you'll also allow people to implement those traits for their own types and implement generic functions over those traits. The Float trait is a really good example of why categorization/hierarchy is unlikely to work well - That trait requires methods like .min_value() which don't make sense for complex numbers, but it is also the interface for .sqrt(), .exp(), and .ln() which have very good definitions for complex numbers. The Float trait in the num crate does not allow me to make generic functions over f32 and Complex<f64> if I want to call .exp().

> For just abs it should only be a few lines of code to make your own

Yeah, the IRC people helped me find a different workaround, but I agree that I'll just make my own trait instead. However, the .abs() methods already exist on all of the signed built in types and so I'll probably call mine .mag() on a Mag trait to avoid confusion (I'm not sure if there would be a collision/compilation error if I used the same names?). This also allows me to implement Mag for unsigned types which is useful for generic code (for examples L1 norms of vectors).

Btw, the docs for i64 have some cut-and-paste errors where they indicate i32 but almost certainly meant i64.


This is already the approach taken with the operator overloading methods with single-method traits like Add, Sub, and so on. Arguably things like .abs() and .exp() also logically belong in the same category and therefore should be implemented as small traits of approximately one method each.


Yeah, that might work, but then it leads to an explosion of traits...

The examples are cut and paste errors in a sense; as it says at the top of the page, the examples are going to often use the wrong number type, because all that code is generated by macros, so for now all the number docs have to use the same type. It's a bug that needs to be fixed, but it's not a trivial one.


> Yeah, that might work, but then it leads to an explosion of traits...

Yes, there are a lot of common math functions, but why is that bad? The alternatives are worse.

> The examples are cut and paste errors in a sense; as it says at the top of the page, [...]

I understand, sorry about that. I didn't see the comment at the top of the page, and I wasn't sure you knew.


Maybe, maybe not. Sounds like a good RFC :)

Also, no worries about the bug! I much prefer over-reporting than under-reporting when it comes to these things.


> Maybe, maybe not. Sounds like a good RFC :)

I'll think about it, but honestly, that sounds super unpleasant. I've seen the bike shedding that happens in those kinds of discussions, and I think it would be difficult to convince any decision makers that there is even a problem if they haven't stumbled upon it already. I don't think many of them do numerical computing, and the language and libraries already scratch their non-numerical itches.


That's fair; I will say that numeric computing is an area we care about. Still working on some of the precursor stuff to make it great, though.

There's a _lot_ of ways you can go in a general purpose programming language; I don't think it's something that "nobody has hit", they just use the workaround of making their own trait(s) and it hasn't been enough of a pain to try and spearhead a change.


This is a pretty neat idea -- I think I'll try this the next time I need to work on numeric code.


"Go is a blub language" was actually my hot take on this article.


You're treading on uncertain ground by insulting Lisp. :)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: