Yeah me neither, i’ve just been dabbling for fun recently. I’ve been dabbling with rust for longer
>> the Go way seems to have more boilerplate
…
switch t := s.(type) {
case Circle:
if t.radius < 10 {
fmt.Println("the rust syntax for this is sweeter")
}
…
https://go.dev/play/p/s4TTZeo7GseDefinitely less boilerplate in the rust version, but i don’t think i go along with it being incomplete or less clear.
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.
Also I prefer with Rust-style sum types that the declaration happens in one place. In the Go version your Shape types could be scattered around all over the place, which makes it harder to parse and understand if you're reading unfamiliar code.
edit: e.g. https://go.dev/play/p/wDO5J8CElSC
enum Shape {
None,
Circle(radius: usize),
}
In your version we've lost the Shape concept, to make it more explicit, what's the idiomatic go version of: enum Shape {
Circle(usize),
Rectangle{length: usize, breadth: usize},
}
https://play.rust-lang.org/?version=stable&mode=debug&editio...In Go code will typically "offer" concrete types, and "accept" abstract interfaces. Abstractions over concrete types are expressed by consumers who want to operate on those types, rather than producers who provide implementations of them. So your Shape would probably end up an interface defined by whatever consuming code wanted to treat Circles and Rectangles equivalently.
Also with Rust for instance you have more robust pattern matching. So you don't have to match only on type, you can match on complex criteria (i.e. foo is a Circle, with foo.radius < 10).
I find this type of programming very expressive and easy to reason about.