Live data from Hacker News

Things Rust shipped without

graydon2.dreamwidth.org

201–210 of 330 posts

Re: Things Rust shipped without

#201
post #68
post #33

Earlier quoted context omitted.

I've never had to use 'goto' in C++ except to break from a nested loop. In C++ labeled breaks would make 'goto' completely obsolete. In C it would still have use in the implementation of orderly error handling -- the pattern where you hand-implement exception handling in C by putting an on_error: label at the end of the function that is goto'd on error. The addition of some orderly construct for this in C would elimi…

A bitecode interpreter is another place where it's nice to have gotos. Here's the base code without gotos: typedef enum { ADD, MUL, ..., END } opcode; void run() { opcode ins; while (1) { ins = fetch_next_inst(); switch (ins) { case ADD: perform_addition(); break; case MUL: perform_multiplication(); break; ... case END: wrap_up(); return; } } } You have 3 jumps on each loop. From the break to the end of the loop, the…

[deleted]

Re: Things Rust shipped without

#202
post #179

Earlier quoted context omitted.

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…

For servers that primarily speak RPC or HTTP, do you foresee Rust going thread-per-request or something more callback-y?

Most applications right now should do thread-per-request. Thread spawning is very optimized in both Rust and the Linux kernel, and you can adjust stack sizes if you need to. If you're hitting limits caused by this, you can use mio.

Re: Things Rust shipped without

#203
post #104

Earlier quoted context omitted.

Still, there are cases where fall-through can be useful: int remaining = length % 4; switch (remaining) { case 3: h ^= (data[(length & ~3) + 2] & 0xff)

Usually I would just factor out the guts of the expression into a little closure in that case. (let f = |x| h ^= ... x ...) LLVM should inline it just fine, and it'll save you typing.

If loops can have specialized control-flow keywords (break; continue), why not let match have one (fallthrough)?

    match x {
        0 => { /* do some stuff */; fall_through; },
        1 => true,
        _ => false
    }
However, I don't know yet how useful it would be. I can't remember ever really needing it, so it would probably need a few practical examples before it became a reality but its an idea.

Re: Things Rust shipped without

#204
post #143
post #6

> 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…

All of the gotos I see on that page are simulations of RAII or labeled break/continue.

Re: Things Rust shipped without

#205

Earlier quoted context omitted.

Usually I would just factor out the guts of the expression into a little closure in that case. (let f = |x| h ^= ... x ...) LLVM should inline it just fine, and it'll save you typing.

If loops can have specialized control-flow keywords (break; continue), why not let match have one (fallthrough)? match x { 0 => { /* do some stuff */; fall_through; }, 1 => true, _ => false } However, I don't know yet how useful it would be. I can't remember ever really needing it, so it would probably need a few practical examples before it became a reality but its an idea.

If we really need it I'd rather have C#-style goto-label instead of explicit fall-through, which is strictly less general. (But I'd almost rather it be a tail-duplicating macro to begin with, since the feature is so rarely needed.)

Re: Things Rust shipped without

#206
post #143
post #6

> 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…

I do not use goto in my code. What do I do wrong? :) Ok, I have to admit that I used it on C64 in the 80s.

Anyways, exceptions are sort of gotos or at least they can behave that way.

Re: Things Rust shipped without

#207
post #151

Earlier quoted context omitted.

M:N threads didn't work for Rust, and they don't have that many advantages anyway even in languages where they do work. There has been a lot of discussion on this over the years and this has been the conclusion everyone came to.

Funny, co-routines have been recently added to C++ and they work wonders. D has fibers which are used extensively and once again, it's a highly desired feature. Go is kind of the poster boy for coroutines and I doubt anyone claims that it doesn't provide many advantages. To be honest it seems to me like your explanation is an attempt to downplay just how nice fibers/coroutines are rather than acknowledge their utilit…

No, his explanation is the few-line summary of years of failed experiments in userspace M:N threading.

Userspace is not equipped to make reasonable scheduling decisions that provide any significant performance advantage, and library/language runtime control of M thread register/stack contexts on top of N kernel threads plays absolute havoc with most operating system's standard libraries.

Go works around this by explicitly not calling into libc et al -- all system calls are issued directly. One big problem with that: directly invoking syscalls is supported on Linux, but NOT supported on OS X.

End result is that Go literally must rely on undefined behavior on any system that does not support direct issuing of syscalls.

From my brief review just now, what MS appears to be proposing for C++17 isn't coroutines in the traditional M:N threading sense, but rather, an explicit mechanism (with syntactical sugar) for capturing reachable variables in a lambda (without preserving the stack), and issuing a call to that magicked-up lambda later via promises.

This is interesting if you love the idea imperative mutable promise-based concurrency, but it's not likely to win you any performance gains, and it's useless in the extreme if imperative mutable promises aren't your cup of tea.

Re: Things Rust shipped without

#208
post #68
post #33

Earlier quoted context omitted.

I've never had to use 'goto' in C++ except to break from a nested loop. In C++ labeled breaks would make 'goto' completely obsolete. In C it would still have use in the implementation of orderly error handling -- the pattern where you hand-implement exception handling in C by putting an on_error: label at the end of the function that is goto'd on error. The addition of some orderly construct for this in C would elimi…

A bitecode interpreter is another place where it's nice to have gotos. Here's the base code without gotos: typedef enum { ADD, MUL, ..., END } opcode; void run() { opcode ins; while (1) { ins = fetch_next_inst(); switch (ins) { case ADD: perform_addition(); break; case MUL: perform_multiplication(); break; ... case END: wrap_up(); return; } } } You have 3 jumps on each loop. From the break to the end of the loop, the…

Okay, but a much more readable and maintainable way to achieve this same optimization is with function pointers.

In your example:

  void (*[10])() function_table = {
      &perform_addition, 
      &perform_multiplication,
      ...
  }
  
  while(1) {
      ins = fetch_next_inst();
      *(function_table[ins])();  
  }
Edit: Seeing it written like this now, it's clear you could save yet another jump by defining a macro for what's in the while loop and putting it at the end of every function call.

Re: Things Rust shipped without

#209
post #68

Earlier quoted context omitted.

A bitecode interpreter is another place where it's nice to have gotos. Here's the base code without gotos: typedef enum { ADD, MUL, ..., END } opcode; void run() { opcode ins; while (1) { ins = fetch_next_inst(); switch (ins) { case ADD: perform_addition(); break; case MUL: perform_multiplication(); break; ... case END: wrap_up(); return; } } } You have 3 jumps on each loop. From the break to the end of the loop, the…

Okay, but a much more readable and maintainable way to achieve this same optimization is with function pointers. In your example: void (*[10])() function_table = { &perform_addition, &perform_multiplication, ... } while(1) { ins = fetch_next_inst(); *(function_table[ins])(); } Edit: Seeing it written like this now, it's clear you could save yet another jump by defining a macro for what's in the while loop and putting…

That's an additional pointer-chase per loop. And more function prefix / suffix work. In actuality, I suspect that it'd be optimized out - but you cannot say "you cannot do X because it relies on compiler optimizations" and replace that with Y that relies on compiler optimizations.

Re: Things Rust shipped without

#210
post #189

Earlier quoted context omitted.

i += ++i; what should be the result ? what is the result in C++ ? (undefined)

If you're making a new language, that example could go a couple of ways: 1. It could be a compiler error. The existence of certain operators doesn't mean they can be combined arbitrarily. 2. Sequence points could be defined differently, allowing for such a convoluted line. This would likely hurt performance, as the compiler would have fewer operations to reorder in each sequence point. Typically, increment and decrem…

I am not sure about if 2 actually would hurt performance in the real world. Remember the whole "must appear to be in order" thing. If the compiler knows that it doesn't change things if they are out of order, it's free to rearrange them.

Note: things like this are part of the potential advantages of static linking.

Post reply on HN