Hacker Read top | best | new | newcomments | leaders | about | bookmarklet login

Not that I agree with your point, but cyclomatic complexity checks are actually implemented as a compiler plugin in rust-clippy project[1]. You'll get a compile time warning if your function becomes too complex.

[1]: https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_c...



sort by: page size:

That is true, although I don't know how helpful that is aside from checking that the annotation is not broken? Much like `const`, the annotation would have to be opt-in either way:

* Rust doesn't infer function types (on purpose)

* like const (or Copy), the removal of the flag is a breaking change, so it should not happen implicitly

So functions would necessarily have to be explicitly marked as e.g. `convergent` or whatever. And while callers of `!`-functions would be easy to check for, I don't think rustc is currently smart enough to infer the totality loops in general.


While it may be convenient, it's truly worrying such (EDIT: was "many") syntactic special cases are going into Rust at this point.

(It may be the case that these things absolutely cannot be handled in a systematic way in a no-GC/no-runtime language, but I'd really like to see some evidence that this is the case.)


Right, and the Rust result also produces a compile-time warning (which can be escalated to an error) if the value isn't checked.

That’s fascinating, what would you say obscures clarity?

Go: https://go.dev/play/p/s4TTZeo7Gse

Rust: https://play.rust-lang.org/?version=stable&mode=debug&editio...

For me, i reckon the Go type machinery is more verbose in this case, e.g. the isShape method to tag Circle as a shape - that just feels awkward to me.

The cyclomatic complexity is identical for both though.


Rust has an optional clippy lint that will warn/forbid all basic arithmetic that might over/underflow, forcing you to use dedicated methods with explicit behaviour instead.

It's very annoying , but I use it in code where this is critical.


There are a lot of operations per line in that code. I would expect anyone interested in maintainability in any language to not write code like this. I don't think this is representative of Rust.

Rust does do the loop condition (well, comparing `my_signed_int` to INT_MAX) even with optimizations: https://godbolt.org/g/dnBEJi

(You need to put a side effect such as I/O in the conditional branch for it not be optimized away, "pub" before the function declaration for it not to be eliminated as dead code, and pass `my_signed_int` as an argument so the condition isn't constant-folded).

Clang OTOH optimizes away the condition with even the lowest optimization level (-Og) turned on, as you'd expect: https://godbolt.org/g/8ftkED


A nice quality of the `guard` in swift is that you can chain multiple conditions, which is harder to do in rust (maybe with some macros a la if_chain?)

It's true that a "checked_as" would come handy from time to time and seems to be in line with the "Rust spirit". But again, since the author seems to be arguing in favor of C it seems like an odd complaint. C even makes it tricky to check for integer overflow while Rust has the checked_ family of functions. In C if you get it wrong it's undefined behavior territory baby.

Ditto with the tuple thing, C doesn't have tuples and won't let you destructure anything.

I guess my overall point is that these complaints seems to pit Rust against some other high level languages like Common Lisp or Haskell but his conclusion is basically "C rulez, Rust droolz".


>I literally don't remember any unpleasant surprises of this form when learning Rust

I can't say I find Rust's pattern matching rules particularly pleasant. The rules are convoluted and arbitrary

https://doc.rust-lang.org/stable/reference/patterns.html

Also, it has often been surprising to me how code that looks like it's entirely read-only will try to move stuff.

E.g, this works:

    let numbers = [1, 2, 3];

    for n in numbers {
        println!("{}", n);
    }

    for n in numbers {
        println!("{}", n);
    }
This doesn't work:

    let numbers2 = vec![1, 2, 3];

    for n in numbers2 {
        println!("{}", n);
    }

    for n in numbers2 {
        println!("{}", n);
    }
I understand why that is and I know how to fix it, but I don't like it. There is a long list of things in Rust that I find understandable but also unpleasant. In that sense it really is a worthy successor to C++. Smart people making unpleasant decisions for good reasons.

Doesn't address the OsString complexity- but the author has another post on strings in Rust that you might be interested in [1]. It at least addresses how Rust does hide a lot of regular `String` complexity that `C` doesn't.

[1] https://fasterthanli.me/blog/2020/working-with-strings-in-ru...


Then maybe rustc ought to have diagnostics that warn if a recursive function won't be optimized fully, and then I can either avoid recursion or rewrite to fit into the optimizer, but having to appease a changing optimizer isn't what I'd call maintainable code, so a function attribute might make more sense.

This is the difference between Rust and C like languages, one optimizes for the usual case and has a simple implementation and the other goes to great lengths to be correct in corner cases at the cost of a lot of complexity.

Never worked with Rust, but I am pretty sure that having a function be pure is not enough to evaluate it at compile time.

A guess: very, very difficult. Writing code to satisfy Rust's checking is not much harder than writing C[1], but converting arbitrary C to satisfy Rust is something completely different.

[1] An' I say it as shouldn't. C is my natural language.


There is a rumor[1] even Rust has yet to get polymorphism right:

>I'm using nalgebra for math. I'll write a bit about it here, because I think it's relevant to Rust as whole. I'm not sure if I actually like it. It's so heavily templated that most of the error messages are impossible to understand, so I usually just double-check what I wrote and try to guess what's wrong. It's also where rust's documentation generator gets in trouble. Signal to noise ratio there is <10%. Not sure how to fix that. Anyway, my point is that maybe it's not always the best idea to write code as generic as possible.

[1]: https://www.reddit.com/r/rust/comments/795dg4/i_spent_the_la...


Even in Rust I don't like chains that go beyond ~4 operations. At some point it becomes clearer when expressed as a loop.

The most principled approach there, I think, would be to build a little Expression data-structure, and then feed it to an evaluation routine, trusting the optimizer to compile the whole thing down to something efficient. If Rust didn't have operator overloading anyway, you could do the job with procedural macros.

In practice, if I had to write that quasi-monstrosity in something like C, I'd probably just comment it as clearly and liberally as possible, to the point where I manage to reassure the reader that the final expression is correct; and then add a // See above: Please DO NOT edit this expression directly!// comment as an extra caution.


Thanks, never wrote Rust so I'm just guessing. What else there is, besides static type checks? Is there a runtime side too?
next

Legal | privacy