5 ms·
I;m sorry there wasn't more talk of Go, I think the author might like some of what Go has to offer. For example, the comparison about maps at the bottom would
by NateDad 12y ago
I;m sorry there wasn't more talk of Go, I think the author might like some of what Go has to offer.
For example, the comparison about maps at the bottom would benefit from seeing the way Go maps work.
There's the single assignment form:
foo := myMap[key]
This returns the zero value of the value type in the map if the key doesn't exist in the map.
and the two valued assignment:
foo, ok := myMap[key]
This returns true or false in ok based on whether the value exists, zero value for foo if it doesn't exist.
This is actually very like an option type, but what go is missing is the compilation-requirement that you check ok before using the value.... however, go does have the compilation requirement that the ok value gets used somehow, or it'll give you an unused variable compilation error. In practice, this works quite well as a more flexible option type for the simple either/or types (either there was a value or an error).
- jmgao 12y agoGo is quite possibly the worst possible language for this example. You don't have generics, so the best you can do with an option type is return an interface {}, and any error checking you have to do has to be done manually. The problem is not that there is no way to do it properly in other languages (well, except lua), the problem is that the most natural way to do it is wrong.
- comex 12y agoI think this is too harsh. Out of the languages mentioned in the article, at least one (JavaScript) has no builtin lookup-or-throw method, and another (Ruby) requires a method call that's significantly uglier than the normal [] syntax, slightly discouraging its use. I don't know enough about the others (besides Python) to speak for them. In comparison, Go's multiple-return lookup thingy might be less natural/obvious than straight usage of foo[bar], but not by much.
- NateDad 12y agoGo has effectively built in option types - multiple returns... And almost every function that can fail uses them. That's what I was trying to say. No, you can't implement actual option types in any kind of reasonable way, but you don't need to.
- Dewie 12y ago> Go has effectively built in option types - multiple returns... They're more like a tuple than an Option type. An Option is a sum type, and a tuple type is a product type... and Option types are never represented as a product type (like tuple) in languages like Haskell, ML, etc. for a good reason. (Aside: why does Go have multiple returns, instead of just using tuples? Or just use structs? They could even call tuples "anonymous structs" if "tuple" is too academic...) Yes, I guess you meant that they can be used like an Option type, somewhat incidentally and indirectly.
- NateDad 12y agoGo doesn't have tuples because they aren't very compatible with compile-time type safety. You could using []interface{} as a tuple, but why would you? Go does have anonymous structs, they're just only of moderate use in a statically typed language (given that you need to specify the types for function arguments and return types) You can do something like this: // make a list of anonymous structs // often useful for table driven tests tests := []struct{ Name string, count int }{ { Name: "First test", Count: 5 }, { Name: "Second test", Count: 7 } } for _, test := range tests { if test.Count > 5 { t.Errorf("%s: expected <= 5, got %d", test.Name, test.Count) } }
- Dewie 12y ago> Go doesn't have tuples because they aren't very compatible with compile-time type safety. What's the problem? Couldn't you have something like: (string, int) For example in the return type of a function? I.e., this function returns a tuple of string and int.
- NateDad 12y agoWhat's the difference between that and multiple returns? You can have func foo() (string, int) func bar(a string, b int) And do bar(foo()) The only thing you couldn't do is make a slice of tuples... But you can make a slice of structs that have just a string and an int. I guess I just don't see a huge amount of utility that isn't otherwise already covered.
- stormbrew 12y agoThe thing that's always annoyed me about the way go does this, where extra return values are treated somewhat specially to encourage you to actually check them, if your function returns only a success/failure condition you're either forced to return a dummy value for no reason and ignore it, or allow the condition to go unchecked. Meanwhile, the actual concept of option type has been around for ages and could have been used instead of trying to twist MRV into it. Thankfully, all the other newer languages are doing the right thing imo.
- NateDad 12y agoNot sure what you mean by needing a dummy value if your function only returns success/failure. That's what a boring old error return is for. func foo() error
- stormbrew 12y agoYes, but unlike having a second result this particular error check need not be touched. To make it so the caller has to check it, I'd have to return a dummy normal return.
- NateDad 12y agoYou can always call a function and not assign the return calls to anything. If you have func foo() (string, error) You can still call it thusly: foo() However there are tools to check for unchecked errors like this one: https://github.com/kisielk/errcheck https://github.com/kisielk/errcheck
- panzi 12y agoWell, Go isn't a dynamic language.
- NateDad 12y agoHeh, good point :)
- Dewie 12y ago> This returns the zero value of the value type in the map if the key doesn't exist in the map. Wow, that's quite horrible (for a static language, anyway). So if my map returns `0`, I can't really be sure whether that is the zero-value (no value at this key), or that the value that I queried actually is `0`. > This returns true or false in ok based on whether the value exists, zero value for foo if it doesn't exist. Better, but still unnecessarily error-prone. > however, go does have the compilation requirement that the ok value gets used somehow, or it'll give you an unused variable compilation error. OK, I can see how that could alleviate the problem in practice: maybe in most contexts, there aren't anything more sensible to use the `ok` variable for than to check its value. In that case, the programmer will be alerted if he tries to use the `foo` variable without checking `ok` first.
- ajuc 12y ago> Wow, that's quite horrible (for a static language, anyway). So if my map returns `0`, I can't really be sure whether that is the zero-value (no value at this key), or that the value that I queried actually is `0`. Replace "0" with null, and it's no different from Java maps.
- Dewie 12y agoI think there is a difference, and for the worse: `0` is a perfectly valid integer value which can be used like any other value. `null` is a valid reference value, but is invalid as far as dereferencing goes; refer NullPointerException. `0` has more potential for propagating through the program, and being erroneously used as a valid map value, while it should really be treated like a sentinel value by the program (no-value-in-map). A reference which is assumed to be valid can only propagate through the program to the point where it is dereferenced, in which case the erroneous assumption will be challenged. It seems like the strong/weak typing distinction: one value can be used freely like any other value, since that is what it is. The other can only be used as a regular value to a degree: it can be passed around, but not actually used.
- ajuc 12y ago