At least that's the kind of thing I've heard about other verbose things you need to do in Go.
The real problem is you’ve just made up a reason that the code is that way, and the reason is also crazy. No language purposefully makes something verbose simply to discourage doing it because of a performance concern. Even if they did, key lookups are constant-time complexity and are among the most efficient things you can do in all of programming. So that wouldn’t even make sense as something you’d want to discourage.
value, _ := map[key]
and if map[key] doesn't exist, value will be set to the "zero value" of the map's type. So Go doesn't force you to handle the error. The actual reason for the "verbosity" is just that you can't simply write if(map[key]) { ...
because map[key] returns two values (and "if" wants to have a boolean expression). But if you really have to do this so often that it's bothering you, you should question yourself why... value := map[key]
and if map[key] doesn't exist, value will (still) be set to the "zero value" of the map's type.The actual reason you cannot simply write:
if(map[key]) { ...
aside from the extraneous parens, is because Go syntax does not permit implicit default values/truthiness in its 'if' statements like that (as you say "if wants to have a boolean expression"). That's the real reason for the verbosity here.But you certainly can write:
if map[key] != "" { ...
if the map contained strings, or: if map[key] { ...
if it contained booleans, etc. (For what that may be worth: checking for default value isn't the same as checking membership in all instances, of course).Because map[key] can in fact return one — or two — values, depending on its usage context.
I guess in this case the real reason is trying to force you to handle the error, and that the error and value are returned separately.
class Foo(val delegate: Collection) : Collection by delegate
{
override fun length() = delegate.length() + 42
}
val foo = Foo(delegate: LinkedList())
foo.add(1)
foo.add(2)
for e in foo {
print(e)
}
foo.removeAll()
foo.length() // = 42
I think a lot of the verbosity I remember was due to the sheer size of the type of interfaces you'd encounter in practice and an inability to easily compose them without implementing your own set of forwarding decorators (io stream style). That and getters/setters or rather the lack of any language-level support for dynamic properties.Personally, I'd just rather take a collection by composition and only expose the small part of the API I actually want.
I guess though this is the standard decorator pattern you'd normally see from GoF.
I can simply do dict.contains("foo") in Java vs having to go through a verbose hoop:
Common operations like filtering/transforming a collections are very concise in Java - I'm certain doing so in Go will take atleast 5x as many lines: Don't get me started on having to go through iota hoops to declare enums.