Live data from Hacker News

A guide to closures in Rust

hashrust.com

11–20 of 102 posts

Re: A guide to closures in Rust

#11
post #3

Earlier quoted context omitted.

It has a massive threshold for beginners for sure. Personally I have a background in C/C++ and moved towards C#, Go, JS etc. With an interest in many more, but the above were my main languages for a decennia. 9 years ago I picked up Go, and have used it the most as my main language since then. 7 Years ago I picked up Rust, but only since 6 months ago really intensive (including publishing the guide that came out of m…

> And sure, plenty of people will tell if you do it "right" you'll have no issues. Go is inspired a lot by CSP, and allows you to apply CSP calculus when using goroutines and channels. It doesn't make it impossible to make mistakes, but it does give you tools needed to reason about your concurrent program, which is more than can be said of most other languages' concurrency support.

And yet goroutines share the same address space, don’t have a good way for the parent to wait for them and even panic silently.

There’s a reason many projects ban the go keyword in favour of a wrapper that fixes some of this.

Go requires constant vigilance, sadly.

Re: A guide to closures in Rust

#12

Earlier quoted context omitted.

> And sure, plenty of people will tell if you do it "right" you'll have no issues. Go is inspired a lot by CSP, and allows you to apply CSP calculus when using goroutines and channels. It doesn't make it impossible to make mistakes, but it does give you tools needed to reason about your concurrent program, which is more than can be said of most other languages' concurrency support.

And yet goroutines share the same address space, don’t have a good way for the parent to wait for them and even panic silently. There’s a reason many projects ban the go keyword in favour of a wrapper that fixes some of this. Go requires constant vigilance, sadly.

Yes, as I said, Go doesn't make it impossible to make mistakes. It doesn't hold your hand and slap you when you go off-road.

But saying it "requires constant vigilance" is an overstatement. As long as you put a little bit of thought in the concurrent code you're writing, it's very easy to do things right. Data races are easy to avoid if you only transfer ownership by sending pointers through channels.

Re: A guide to closures in Rust

#13
post #3

Earlier quoted context omitted.

It has a massive threshold for beginners for sure. Personally I have a background in C/C++ and moved towards C#, Go, JS etc. With an interest in many more, but the above were my main languages for a decennia. 9 years ago I picked up Go, and have used it the most as my main language since then. 7 Years ago I picked up Rust, but only since 6 months ago really intensive (including publishing the guide that came out of m…

"And sure, plenty of people will tell if you do it "right" you'll have no issues." My answer to that is always that if you are able to do it right in C or C++ (and maybe golang) you should not run into any issues with Rust. Especially you should not ever have to fight to borrow checker because it does the job you should be doing as a C/C++ programmer in your head anyway.

> Especially you should not ever have to fight to borrow checker because it does the job you should be doing as a C/C++ programmer in your head anyway.

It adds mental overhead.

I don't even like the "const" qualifier for functions in C++. It is so hard to get a design right upfront when thinking about non trivial 'const'-chains.

Re: A guide to closures in Rust

#14

Earlier quoted context omitted.

And yet goroutines share the same address space, don’t have a good way for the parent to wait for them and even panic silently. There’s a reason many projects ban the go keyword in favour of a wrapper that fixes some of this. Go requires constant vigilance, sadly.

Yes, as I said, Go doesn't make it impossible to make mistakes. It doesn't hold your hand and slap you when you go off-road. But saying it "requires constant vigilance" is an overstatement. As long as you put a little bit of thought in the concurrent code you're writing, it's very easy to do things right. Data races are easy to avoid if you only transfer ownership by sending pointers through channels.

It would’ve been trivial to make the language disallow nil, separate goroutine address spaces, crash the process on unhandled panic in any goroutine, etc.

The reason Go annoys people is the unforced errors. Sure, it gets a lot right. But what it gets wrong had solutions long before Go existed and those solutions were wilfully ignored.

Re: A guide to closures in Rust

#16
post #3
post #2

> I'll explain what the move keyword does later in the article. For now just trust me that it is needed for the code to compile. That does not take a lot of trust, after a few rounds with that compiler. At least error messages are good with the Rust compiler. I've got very limited experience with Rust, but it does seem like a language with a massive threshold for beginners.

It has a massive threshold for beginners for sure. Personally I have a background in C/C++ and moved towards C#, Go, JS etc. With an interest in many more, but the above were my main languages for a decennia. 9 years ago I picked up Go, and have used it the most as my main language since then. 7 Years ago I picked up Rust, but only since 6 months ago really intensive (including publishing the guide that came out of m…

Thanks for your insight.

Re: A guide to closures in Rust

#17

Earlier quoted context omitted.

Yes, as I said, Go doesn't make it impossible to make mistakes. It doesn't hold your hand and slap you when you go off-road. But saying it "requires constant vigilance" is an overstatement. As long as you put a little bit of thought in the concurrent code you're writing, it's very easy to do things right. Data races are easy to avoid if you only transfer ownership by sending pointers through channels.

It would’ve been trivial to make the language disallow nil, separate goroutine address spaces, crash the process on unhandled panic in any goroutine, etc. The reason Go annoys people is the unforced errors. Sure, it gets a lot right. But what it gets wrong had solutions long before Go existed and those solutions were wilfully ignored.

> It would’ve been trivial to make the language disallow nil

Which would interfere with Go's philosophy that zero should be a valid (usable) state for types. What would be the default value of a reference type without nil?

> separate goroutine address spaces

This is not trivial to implement. The only way I can think of is to start each goroutine in a new process, which brings along other downsides - everything must be copied, cannot pass file/socket handlers between goroutines, etc. Doesn't seem to be worth it.

> crash the process on unhandled panic in any goroutine

Go does crash the process on unhandled panic in any goroutine:

    # main.go
    package main

    func main() {
        go func() {
            panic("hehe")
        }()

        for {
        }
    }

    # go run main.go
    panic: hehe

    goroutine 5 [running]:
    main.main.func1()
            /[...]/main.go:5 +0x27
    created by main.main
            /[...]/main.go:4 +0x25
    exit status 2
> The reason Go annoys people is the unforced errors.

This is the criticism I've also had, and raised an issue on GitHub. Unfortunately, it's impossible to fix this without breaking backwards compatibility.

> But what it gets wrong had solutions long before Go existed and those solutions were wilfully ignored.

They were wilfully ignored, but only because the tradeoffs didn't seem worth it at the moment. You make it sound bad, as if Go devs were simply high on crack and knew what they doing was wrong, but did it anyways, when in reality it's more of a case of those "solutions" not being compatible with the goals of the language, or simply nobody coming up with an elegant way to incorporate it.

Re: A guide to closures in Rust

#18

Earlier quoted context omitted.

It would’ve been trivial to make the language disallow nil, separate goroutine address spaces, crash the process on unhandled panic in any goroutine, etc. The reason Go annoys people is the unforced errors. Sure, it gets a lot right. But what it gets wrong had solutions long before Go existed and those solutions were wilfully ignored.

> It would’ve been trivial to make the language disallow nil Which would interfere with Go's philosophy that zero should be a valid (usable) state for types. What would be the default value of a reference type without nil? > separate goroutine address spaces This is not trivial to implement. The only way I can think of is to start each goroutine in a new process, which brings along other downsides - everything must b…

Sum types let you have default values without pervasive nil. That’s not new either, it’s been done since at least ML.

Separate address spaces are trivial when you have a runtime, just look at Erlang.

Go could’ve also copied Erlang’s supervision trees to ensure safe and bounded goroutine lifetime.

For all their impressive achievements, Go’s creators suffer from extreme NIH syndrome. Just look at Plan 9.

Re: A guide to closures in Rust

#19

Earlier quoted context omitted.

> It would’ve been trivial to make the language disallow nil Which would interfere with Go's philosophy that zero should be a valid (usable) state for types. What would be the default value of a reference type without nil? > separate goroutine address spaces This is not trivial to implement. The only way I can think of is to start each goroutine in a new process, which brings along other downsides - everything must b…

Sum types let you have default values without pervasive nil. That’s not new either, it’s been done since at least ML. Separate address spaces are trivial when you have a runtime, just look at Erlang. Go could’ve also copied Erlang’s supervision trees to ensure safe and bounded goroutine lifetime. For all their impressive achievements, Go’s creators suffer from extreme NIH syndrome. Just look at Plan 9.

Sum types are optional. And if you make them obligatory, they become just syntax sugar for nil. What would be the default value of a non-sum reference type, without nil?

Erlang's "address space isolation" is not real address space isolation, only semantic. Erlang "processes" are all still in the same address space, but the language semantics doesn't allow them to interfere with one another.

You can implement bounded goroutine lifetime by using sync.WaitGroup and other constructs for coordinating goroutines. Go just doesn't force you to.

> Go’s creators suffer from extreme NIH syndrome. Just look at Plan 9.

This is just bad faith arguing. Plan 9 was revolutionary in many ways, and brushing it off as just NIH makes me think you don't understand or recognize its achievements.

Re: A guide to closures in Rust

#20

Earlier quoted context omitted.

Sum types let you have default values without pervasive nil. That’s not new either, it’s been done since at least ML. Separate address spaces are trivial when you have a runtime, just look at Erlang. Go could’ve also copied Erlang’s supervision trees to ensure safe and bounded goroutine lifetime. For all their impressive achievements, Go’s creators suffer from extreme NIH syndrome. Just look at Plan 9.

Sum types are optional. And if you make them obligatory, they become just syntax sugar for nil. What would be the default value of a non-sum reference type, without nil? Erlang's "address space isolation" is not real address space isolation, only semantic. Erlang "processes" are all still in the same address space, but the language semantics doesn't allow them to interfere with one another. You can implement bounded…

An Optional defaulting to None when created can still fail to compile if you don't check whether it's None when you use it. Same with a Result defaulting to an Error.

The problem with nil for any pointer or interface is that you can compile code dereferencing it without first checking if it's nil.

Post reply on HN