8 ms·
First, please don't compare Go and Rust. They are completely different languages with completely different target use cases. Go has very different design goals
by chimeracoder 12y ago
First, please don't compare Go and Rust. They are completely different languages with completely different target use cases. Go has very different design goals than Rust, so very little that Rust does would actually be possible in Go, and vice versa.
> Go code often passes references over channels, which results in shared memory between two threads with no locking
Having a complex type system would cut into compile times (an explicit primary design goal, to the point where the Go compiler must be written to read each file exactly once[0], no more).
As for the code you're referring to, Go is not designed to be a language which prevents you from shooting yourself in the foot with provable code. It's designed to be a language which makes it reasonably easy to be sure you haven't, as long as you follow the general idioms and best practices. What you're describing here is definitely not one - I can think of a few instances in which pointers might be reasonably passed over a channel, but they're few and far between.
Also, I would think it's pretty obvious that once you've sent something over a channel you shouldn't try and write to it anymore[1]. Do you have an example of the code you're referring to?
[0] well, technically "at most once", since some files can be skipped entirely.
[1] I'd need to think about this, but I don't think it'd be difficult to detect this statically[2] at compile-time and enforce that stack-allocated rvalues into channels are never used again in the same scope. It's definitely possible to extend `go vet` to handle this, and it may even be possible to write this in as a compiler error in a future version of Go.
[2] Incidentally, one of the reasons that it's so easy to do reliable static analysis on Go code (compared to other languages) is that the grammar is incredibly simple - it's almost entirely context-free, which is very rare among non-Lisps. Having a more complex type system usually requires at least some additional syntax to along with this, which means you'd have to start sacrificing this design goal as well in order to create a more elaborate type system.
- pcwalton 12y ago> (an explicit primary design goal, to the point where the Go compiler must be written to read each file exactly once[0], no more). Same in Rust. Thanks to the module system, the Rust compiler never rereads a file more than once. > [1] I'd need to think about this, but I don't think it'd be difficult to detect this statically[2] at compile-time and enforce that stack-allocated rvalues into channels are never used again in the same scope. It's definitely possible to extend `go vet` to handle this, and it may even be possible to write this in as a compiler error in a future version of Go. That trivially fails to solve the problem, due to aliasing. > [2] Incidentally, one of the reasons that it's so easy to do reliable static analysis on Go code (compared to other languages) is that the grammar is incredibly simple - it's almost entirely context-free, which is very rare among non-Lisps. Having a more complex type system usually requires at least some additional syntax to along with this, which means you'd have to start sacrificing this design goal as well in order to create a more elaborate type system. Rust's grammar is also context-free, as far as I know. Your proposed static analysis is not reliable. The "more complex" type system in Rust exists precisely so that we can do more reliable static analysis.
- steveklabnik 12y ago> Rust's grammar is also context-free, as far as I know. I believe bytestrings are context-sensitive :( I don't remember the exact details here, so I could be wrong. But other than that...
- nikomatsakis 12y agoTechnically, byte-strings (and nested comments) mean the lexer is not regular, but the grammar is still context-free. But anyway, parsing is not typically the bottle-neck these days.
- pcwalton 12y agoOh, that's just lexing though.
- Gankro 12y agoraw strings: https://github.com/rust-lang/rust/blob/master/src/grammar/raw-string-literal-ambiguity.md https://github.com/rust-lang/rust/blob/master/src/grammar/ra...
- chimeracoder 12y ago> > (an explicit primary design goal, to the point where the Go compiler must be written to read each file exactly once[0], no more). > Same in Rust. Thanks to the module system, the Rust compiler never rereads a file more than once. As I said right at the beginning of my post, I'm not trying to compare Rust and Go directly, because I don't think that's meaningful. I'm explaining why these particular features would be difficult to incorporate into Go. Note that I never said that Rust reads a file more than once, or that Rust's grammar is not context-free. In fact, the word "Rust" doesn't appear anywhere in my comment at all except in that very first paragraph. I love talking about PLT and would otherwise be interested in having a discussion about static analysis and hearing why you think it would not solve the problem, but I have to say, it's both frustrating and discouraging to post an in-depth response and then get downvoted twice, with the only reply being one which very clearly ignores the very first line of my entire response.
- look_lookatme 12y ago> First, please don't compare Go and Rust. They are completely different languages with completely different target use cases. Go has very different design goals than Rust, so very little that Rust does would actually be possible in Go, and vice versa. Almost all languages are different and thus have different design goals. That doesn't mean it should be off-limits to compare them.
- loudmax 12y agoYeah, but instead of having an interesting discussion about Rust, much of the thread devolves into a pissing contest.
- ajross 12y ago> First, please don't compare Go and Rust. They are completely different languages with completely different target use cases. Then why does everyone insist on comparing Rust and C++? Objectively Rust is much closer to Go than to C++. That's just dumb. Rust and Go were, in fact, contemporarily designed to similar constraints and with similar goals. That they made significantly different design choices is an interesting point that should be discussed and not swept under the rug just to win internet points.
- Jweb_Guru 12y agoAt the language level, Rust is substantially more similar to C++ than it is to Go. C++ and Rust both have many properties (lack of GC, pervasive stack allocation [even for closures], move semantics, overhead-free C FFI compatibility) that many other languages lack, and the Rust developers actively work to match C++ on features. None of this is true for Go; Rust's similarities with Go are shared by many other languages as well, many of which are much more widely used than either (hence would probably represent a more informative comparison; e.g. I think posts contrasting Rust and Java would be quite useful, but I have seen very few of them). As such, Go and Rust comparisons tend not to be very illuminating.
- pcwalton 12y ago> At the language level, Rust is substantially more similar to C++ than it is to Go. C++ and Rust both have many properties (lack of GC, pervasive stack allocation [even for closures], move semantics, overhead-free C FFI compatibility) that many other languages lack, and the Rust developers actively work to match C++ on features. I think this is absolutely true, for what it's worth.
- ademarre 12y agoRust and Java? Not the usefulness you're looking for, but this tool popped up on HN today: http://rosetta.alhur.es/compare/Rust/Java/# http://rosetta.alhur.es/compare/Rust/Java/#
- steveklabnik 12y ago
- detrino 12y ago> First, please don't compare Go and Rust. They are completely different languages with completely different target use cases. Go has very different design goals than Rust, so very little that Rust does would actually be possible in Go, and vice versa. It's perfectly reasonable to compare any two programming languages, especially where their use cases overlap. > As for the code you're referring to, Go is not designed to be a language which prevents you from shooting yourself in the foot with provable code. It's designed to be a language which makes it reasonably easy to be sure you haven't, as long as you follow the general idioms and best practices. What you're describing here is definitely not one - I can think of a few instances in which pointers might be reasonably passed over a channel, but they're few and far between. Absolutely sure is better than reasonable sure.
- steveklabnik 12y ago> Having a complex type system would cut into compile times At least in Rust, type checking takes basically no time compared to things like optimization passes.
- copsarebastards 12y ago> Go has very different design goals than Rust, so very little that Rust does would actually be possible in Go, and vice versa. Oh give this lame argument a rest already. They're both supposedly general-purpose programming languages. Rust shoots for a little lower level than Go, but they can certainly be compared, and the comparisons are valid. > Having a complex type system would cut into compile times (an explicit primary design goal, to the point where the Go compiler must be written to read each file exactly once[0], no more). I'm not sure how this is a defense of Go: yes, that's a primary design goal; it's also a terrible design goal. Trading an adequate type system for a short-term gain in compile time is an amateurish mistake. Compilation time can be mitigated on even the largest projects by only rebuilding changed modules. If you're getting to the point that this isn't working, then maybe it's time to start working on reducing the size of your code. I've worked on projects that were 500,000 lines of code and compile time was sometimes an issue, but not nearly as large an issue as bugs which would have been caught by an adequate type system (large C#/Java codebases pre-generics). > As for the code you're referring to, Go is not designed to be a language which prevents you from shooting yourself in the foot with provable code. It's designed to be a language which makes it reasonably easy to be sure you haven't, as long as you follow the general idioms and best practices. What you're describing here is definitely not one - I can think of a few instances in which pointers might be reasonably passed over a channel, but they're few and far between. We've tried this approach before, many, many times, and the result has been high-profile bugs. The fact is, these "idioms and best practices" will not be followed perfectly on projects of any reasonable size if they are not enforced by code. Why would you not enforce them with code? And if you're designing a language, why not design the language in such a way as to allow code enforcing best practices? Like, a type system? > Also, I would think it's pretty obvious that once you've sent something over a channel you shouldn't try and write to it anymore[1]. Yes, just like it's pretty obvious that when you free memory you shouldn't write to it any more. We've never had any issues with that, now have we? > It's definitely possible to extend `go vet` to handle this, and it may even be possible to write this in as a compiler error in a future version of Go. I didn't know about `go vet` and I wish I didn't. So, to avoid a second pass over the code during compilation, you add a second pass over the code during `go vet` that has less capabilities. Good thinking. I'll add that onto the list of other stupid ideas that have been tried decades ago and didn't work but are finding new life in Go. > Incidentally, one of the reasons that it's so easy to do reliable static analysis on Go code (compared to other languages) is that the grammar is incredibly simple - it's almost entirely context-free, which is very rare among non-Lisps. Having a more complex type system usually requires at least some additional syntax to along with this, which means you'd have to start sacrificing this design goal as well in order to create a more elaborate type system. Yes, adding syntax for static type checking will definitely make static analysis like type checking harder. Are you fucking kidding me?
- rdtsc 12y ago> They are completely different languages with completely different target use cases. Go has very different design goals than Rust, so very little that Rust does would actually be possible in Go, and vice versa. But everyone keep trying to though, that's kind of interesting. The reason I am guessing is because Go billed itself as a "systems programming langauge". It did, go find the original announcement video (or was it a press release). That is what it said. Later after replacing C idea didn't quite materialize. They clarified that they mean "systems programming language" to mean something else actually. Now if I said that or some other anonymous user, ok, fine, people get confused, don't know enough etc etc. But I don't believe Rob Pike doesn't know what a systems programming language is. Anyway, I am not saying one way or another but just illustrating that everyone doing the comparison is not completely insane. Now they way I see Go is more like a Python++ or Ruby++. All those nice concise languages, + concurrency, + speed, + some type safety, + easy static binary deployment. So I agree with you that Rust and Go should not be compared.
- cmrdporcupine 12y agoMy perspective is that Go seems to be trying to aim at network aware services where Java might have been used before. Internally what I've seen @ Google is it seems to be used here and there for services where Google teams have typically used C++ (but other companies might use Java.) And yes, some places where Python has been used, Go makes a decent replacement. Not my cup of tea, but I can see its niche. It's not the same niche as Rust. At least not right now.
- hyperpape 12y agoMy understanding is that most languages are context free in their syntax, but that type checking and namespace "stuff" are (almost?) always context-sensitive.