> animals := []Animal{Dog{}, Cat{}, Llama{}, JavaProgrammer{}}
> for _, animal := range animals {
> fmt.Println(animal.Speak())
> }
> }
This makes my eyes hurt. In this modern age we still haven't learned to create easy to read languages?
There's a lot going on in about 3 lines.
n = sum(x for x in my_sequence if x % 2 == 0)
But the Go code listed above is not just plagued with a lot going on in "3 lines". I think there's something to be said about gratuitous operators, and a sort of beauty to letting the parser do more work than the programmer themselves. I don't use Go at all, but from the example above I can tell it is a horribly grotesque language considering when it was created. Sure, even C or C++ have curly braces and array specifiers for types; however, at least these have the excuse of age and compatibility to work with. Go is relatively new, and I think that welder was getting at is that syntax shouldn't be some overly complex thing in this day and age. Nim and Elixir come to mind as two (newer) languages that avoid many syntax warts without making significant trade-offs because of it.The only place an error could occur in this code is if fmt.Println returns an error. What should happen if you can't display the output? Try to print an error? This is entirely appropriate for demo code and use of stdout like this. No one honors the return value from printf(3) in demo code either. Considering other languages, Python's print functionality doesn't have anything about returning or raising errors, and it wasn't even available as a function until 2.6.
Or to give a concrete example, say you want to do formatted output to stderr. How is one supposed to determine that os.Stderr is something that can be passed to fmt.Fprintf? Is there a better way than manually comparing method signatures?
type File struct {
...
}
var _ io.Writer = (*File)(nil)
It's not a panacea, but it helps. If you write all your own code this way, at least it will be easy to see which interfaces your own types implement, and (with a grep or GoRef) vice versa.Plus you get interface implementation checking, so your error messages actually make sense if the interface or type method signatures unexpectedly change.
Again, this is not a real solution to your problem, but it has enough advantages to be worth mentioning.
> func (j JavaProgrammer) Speak() string { > return "Design patterns!" > }
shrug At least our language designers trusted our intelligence enough to implement generics.
Trusted you so much that they even tripped on co/contravariance to add to the challenge :p
>A method call x.m() is valid if the method set of (the type of) x contains m and the argument list can be assigned to the parameter list of m. If x is addressable and &x's method set contains m, x.m() is shorthand for(&x).m()
In other words, if a type T no method M, it will look for M in *T's methods.
https://news.ycombinator.com/item?id=9320235
The blog post is from 2012.