I'd like Rust to be shipped without counterintuitive standard library function names and that book with all its style 'recommendations'. And I'd like the Rust compiler to be shipped without that non-snake case warning enabled by default. Language creators won't endear themselves to me by ranting. The problem I have with Rust is _not_ the language itself.
This is the first I've heard complaints that Rust is too strict with formatting. If anything, the popularity of gofmt (which is far more opinionated than rustc's default warnings are!) is a testament to the fact that people want languages to be ruthlessly opinionated regarding style these days.
Things Rust shipped without
171–180 of 330 posts
Re: Things Rust shipped without
#172Earlier quoted context omitted.
That's what I mean. Why should I even care about stuff like this being "considered poor style" by the creators of Rust? "Poor style" is what doesn't work well for my team and me.
> Why should I even care about stuff like this being "considered poor style" by the creators of Rust? Maybe you are writing code for the Rust standard library, where following the core projects style recommendations would be important for consistency. Maybe you don't want to start from scratch coming up with your own style, and want a decent starting point from which you can vary as your team figures out what does/do…
Re: Things Rust shipped without
#173Earlier quoted context omitted.
The idea that "[u]sing a return as the last line of a function works, but is considered poor style" irks me so much. A lot of what I find appealing about Rust is that it makes so much explicit through its type system, so I don't understand the philosophy behind preferring implicit returns, especially since you could have a scenario where someone hasn't finished writing a function but it still compiles without error.
Implicit returns encourage functional style; foo.map(|x| x + 1) is so much nicer than foo.map(|x| { return x + 1; }). Once you have implicit returns in closures, you might as well have them everywhere for consistency.
"Nicer" is a subjective thing. BTW in the trivial case above one may judge this or that to be nicer, but in a large method, 'return func(a,b,c)' is obvious, whereas looking at 'func(a,b,c)' it is super non-obvious that the value is being returned.
Re: Things Rust shipped without
#174Earlier quoted context omitted.
defer has unavoidable runtime overhead due to its dynamic semantics. It's strictly slower than RAII as implemented in C++ or Rust.
That's not true. The only case where the runtime overhead is unavoidable is calling defer in a loop, because it might require allocating the defer chain in the heap; in all other cases, it's just a metter of writing the correct optimization passes in the compiler.
Re: Things Rust shipped without
#175Earlier quoted context omitted.
> The addition of some orderly construct for this in C would eliminate that case, leaving no real role for goto there either. I like the way this is handled in Go with the defer keyword: https://blog.golang.org/defer-panic-and-recover This construct gives you most of the power of C++ RAII without the overhead. Except that you can't use it to cleanup resources after exiting an anonymous block—it strictly defers to fun…
defer has unavoidable runtime overhead due to its dynamic semantics. It's strictly slower than RAII as implemented in C++ or Rust.
I hadn't considered the type of overhead you're talking about, which is admittedly more important for the kind of software that tends to get written in C.
Re: Things Rust shipped without
#176> goto (not even as a reserved word) I haven't done this for a while, but once upon a graduate program I wrote a compiler from a made-up-language (MUP) to C. MUP had some strange control structures, and if C did not have "goto", it would have been a lot more difficult to implement those structures. Since then, I have always thought languages should have a "goto" statement that human-written code is not allowed to use…
I've always defended goto and gotten a lot of flak for it. As soon as I say, "I wish I had X-language had gotos", I see jaws drop. Response: "Wow, haven't you heard the news?! GOTOs are considered harmful!" I think goto should be in almost every language. It's one of the most primitive instructions, why shouldn't it be available when needed? Yes, it can be misused, just like any other feature in the language , but it…
What if I just avoid contributing to the ncurses codebase? I've used plenty of useful tools with absolutely horrific codebases that I'd never want to touch in a million years. Not sure if ncurses is one of them.
The whole "it gets used, ergo it must be a good idea" argument doesn't hold much traction with me - even if I think using it when in C, to enforce single exit style, to work around the lack of RAII constructs, goto is the lesser evil.
I started with GOTO in BASIC. I used it a lot. It structured my initial reasoning about control flow. Despite this, in the past few years, I've used a naked goto maybe once or twice, and in all cases later rewrote it without the goto, which in my opinion increased it's readability. (I generally always have the option of C++ over C, and choose it, rendering single exit style 'useless'.)
> Oh, here's tmux, if you're interested (one of the most beautifully written C programs): https://github.com/tmux/tmux/search?utf8=%E2%9C%93&q=goto
Most of those are single exit style gotos. Those that aren't, do cause some concern, despite being "one of the most beautifully written C programs", even to their original author from the looks of it:
if (errno == ENOMEM)
goto retry; /* possible infinite loop? */
For what it's worth, it seems unlikely to be an infinite loop, short of encountering a bug in sysctl, or another process/thread constantly adding data. I had to google the header path to find an appropriate manpage (i.e. not _sysctl, not sysctl the program) to figure this out...I've encountered worse edge cases before, however, and I'd really prefer my programs crash properly, instead of hanging when they do.
> State machines, for example, can make good use of gotos.
The performance complaints about an additional branch misprediction when using the "for(;;) switch(...)" style without gotos, is one of the few arguments that moves me, if only slightly. That seems like a case your standard optimizing compiler really should be able to handle, however. I'll assume they don't, as I'm too lazy to test if this is merely hearsay...
That said, I'll even use "goto case" in C# on occasion where I'd use case fallthrough in C++, if I'm feeling particularly lazy and don't want to turn things into proper method calls that can simply call each other just yet. I usually clean it up before I start to confuse myself.
It's not something I'd miss if it were gone, however. It's something I use only rarely, and only as a crutch to stave off cleanup. Not exactly a ringing endorsement.
EDIT: Code formatting, proper insertion of subject...
Re: Things Rust shipped without
#177Earlier quoted context omitted.
defer has unavoidable runtime overhead due to its dynamic semantics. It's strictly slower than RAII as implemented in C++ or Rust.
To clarify, I meant the "overhead" of defining and instantiating a container class for RAII purposes. I hadn't considered the type of overhead you're talking about, which is admittedly more important for the kind of software that tends to get written in C.
Re: Things Rust shipped without
#178Earlier quoted context omitted.
That's not true. The only case where the runtime overhead is unavoidable is calling defer in a loop, because it might require allocating the defer chain in the heap; in all other cases, it's just a metter of writing the correct optimization passes in the compiler.
Yes, that's what I meant by "strictly slower". At best, it can be optimized to something similar to what RAII can give you. RAII never has the overhead of the bad case.
In all other cases (which is almost all usages), it is semantically equivalent to RAII, so the language doesn't force any runtime overhead. The only difference is that the compiler is less mature than an average C++ compiler, but this is an implementation problem, not a design problem.
RAII has no overhead because it is a pattern designed within the context of a zero-overhead language. defer allows you to implement a superset of cases that RAII handles, including those with runtime overhead.
Re: Things Rust shipped without
#179Earlier quoted context omitted.
> they don't have that many advantages anyway even in languages where they do work. Are you sure about that? One of the main advantages of coroutines/greenlets IMO is writing simple and straightforward blocking code (e.g. an echo server); without them, you either need to use threads (which are slower and much more heavyweight) orcallbacks or related constructs (async/await, futures, ...).
Threads aren't that slow on Linux. The main advantage of M:N threading as implemented in Go over 1:1 is that spawning is fast and doesn't use much memory, because you can avoid the syscall and only a small (initial) stack is required. Rust can't do the latter because it's not GC'd. Even if it could, many real-world servers actually do non-trivial work in their threads, so the cost of spawning a thread is dwarfed by t…
Re: Things Rust shipped without
#180Earlier quoted context omitted.
Serialization is usually done better with macros, for performance reasons. We now have Erick Tryzelaar's fantastic serde library for high-quality serialization, competitive with rapidjson.
Oh, serde is interesting. I was specifically thinking about compile-time reflection but apparently rust's macros are more powerful than I realized. I'm inspired to look into this more, thanks!