11 ms·
Some thoughts after spending ~100 hours with Go. - Function overloading is a major convenience that you will miss. There are differently named versions of ever
by n1ghtm4n 13y ago
Some thoughts after spending ~100 hours with Go.
- Function overloading is a major convenience that you will miss. There are differently named versions of every function and you will call the wrong version with the wrong arguments all the time. The number of functions in the standard library could be reduced by at least 1/4 if they'd got this right. The official FAQ (http://golang.org/doc/faq#overloading http://golang.org/doc/faq#overloading) explains that leaving out overloading is "simpler", meaning simpler for them.
- Default parameters are a major convenience that you will miss. Using strings.Replace() to remove some chars from a string? Don't forget to pass the -1 at the end, asshole! The -1 says don't put a limit on the number of replacements. In Python there would be a max=None default parameter and this would never bite anyone.
- No named arguments, because fuck readability.
- Forcing me to handle errors is great. Having 20 different ways to do it is not great. Examples: fmt.Errorf(), fmt.Fprintf(os.Stderr), errors.New(), log.Fatal(), log.Fatalf(), log.Fatalln(), panic/recover...
- Using && and || for logical operators in this day and age is just ridiculous. Why do people keep inventing programming languages as if Python doesn't exist?
- Don't think that just because the Unicode guys invented Go that Unicode is going to be easy. Their solution is not to create an airtight abstraction layer between chars (or "runes" WTF?) and integers. Their solution is to provide almost no abstraction and force you to deal with the inherent integer-ness of all characters. Example:
In Python:
len("нєℓℓσ") # 5, because there are 5 chars
In Go:
len("нєℓℓσ") // 12, because there are 12 bytes
utf8.RuneCountInString("нєℓℓσ") // 5, plz kill me i am an abomination
tl;dr If you're inventing a programming language for human beings (not UNIX gods), try it out on a group of smart high school students first. It will be a humbling experience.
- dbaupp 13y ago> Using && and || for logical operators in this day and age is just ridiculous No it's not, it takes 10 minutes to learn that && means and and || means or (maybe a little longer to get the hang of it properly), and this knowledge transfers to many programming languages. (This is a little like arguing "we shouldn't use + when English has a perfectly good word 'add'"; symbol reasoning is valuable.)
- count 13y ago'+' is damn near universal. '&&' && '||' !universal.
- dbaupp 13y agoThey're not universal, but they're essentially so; pretty much everyone who's used C(++), Java, C#, ... has seen && and ||, and knows what it is. And people who've only used languages with 'and' and 'or' will only take a few minutes to get up to speed (they have the option of spending longer complaining about it if they want).
- anona 13y agoI don't think the argument is that people can't understand '&&' and '||', but that using 'and' and 'or' is a better choice.
- jussij 13y agoSo what do you do about the bitwise and and or operations. How should they be expressed? Python expresses the bitwise and and or using the & and | characters, the exact same characters as Go. And that also explains why Go chooses to use && and || for and the logical and or operators.
- anona 13y agoThe code is much more readable if the bitwise operators do not look almost identical to the logical ones.
- ak217 13y ago> people who've only used languages with 'and' and 'or' will only take a few minutes to get up to speed No. Cognitive overhead. You pay for it every time you parse these words in your brain. You pay for it by reducing the number of nested/combined clauses that you can parse on the fly. (This is far from the only readability issue with Go, by the way, and you're right in that it's among the more superficial ones. The language is designed so well in all ways except the one that matters the most, it hurts.)
- callenish 13y ago> In Go: len("нєℓℓσ") // 12, because there are 12 bytes utf8.RuneCountInString("нєℓℓσ") // 5, plz kill me i am an abomination I'm not sure I understand your objection. Bytes and UTF8 characters are different things, and you can't abstract away the difference. There are also times, perhaps the majority of times, when you will need the byte count of a UTF8 string. That means you need at least two different length functions for strings and they need different names. Shouldn't UTF8-specific things live in the utf8 namespace? Some programs won't need any string handling, after all, and it would be a waste to include code they never used. Assuming you can allow the utf8 namespace as sensible, would you feel better if there was a RuneLen() function aliased to RuneCountInString()? If you are that upset about it, then my suggestion is to explain your rationale and submit a patch[1] to provide the alias. It's not like it would be hard to code. Perhaps you might convince people and get it in the next release. [1] http://golang.org/doc/contribute.html http://golang.org/doc/contribute.html
- skizm 13y agoI think the majority of the time you want the number of utf8 characters and not the byte count. In fact I have never wanted the byte count. If I did I would expect something like byteLen and Len. Not the other way around. You should be optimizing the common case, not the exception. Obviously I'm not a language designer so perhaps I'm talking out of my ass but I've heard this complaint A LOT.
- callenish 13y agoHave you never had to indicate how many bytes you are sending over a stream, say in the Content-Length of an HTTP response? Have you never put strings into a byte buffer? But that doesn't matter. Let's say you are correct: when working with strings, you more often want the rune length. It still wouldn't be the right decision, given the other design decisions of Go, because it would have needlessly complicated things with only arguable benefits. Let me show you what I mean. The len() function works with a whole lot of things: strings, arrays, slices, maps and channels. For the first three, len() returns the number of bytes involved. This is because all three are backed by an array, and so sensibly have similar semantics. It would have violated the principal of least surprise for anyone who knew the language to have an array-backed storage not return a byte count. Both the language developers and the users of it would have to special-case strings, in code and in their brains. Now, they could have decided to do it anyway, but then another surprise awaits. What happens when you take a slice of a string? Oh no, more special casing and more complication for everyone. The Go developers do special-case where doing so would clearly be a win for their users. Consider range, which iterates by runes over a string, potentially moving the index on the underlying array forward by more than 1 on each pass. That is clearly going to be the most common usecase the user is going to want and so was worth doing. It also eliminates many of the usecases where getting the length of a string in runes would matter to you. Not all, but a lot.
- derefr 13y ago> between chars (or "runes" WTF?) and integers. "Runes" were the original name, as implemented in Plan 9 by the same folks, for what the standards committee later decided to call the relatively blaze term "Unicode codepoints"--and which are not quite the same thing as characters. (In fact, I would say that the notion of a Unicode "character" is ambiguous to the point of uselessness--there are glyphs composed from several codepoints (base glyph + combining accents), which should be treated as one "character"; there are ligatures that hold single codepoints, but which semantically are multiple "characters"; there are stacking languages where one "character", representing a whole word, will be composed together from several codepoint "radicals"; while in other ideographic languages, each pre-composed idea-part is its own "character" and has its own codepoint; and so forth.)
- wisty 13y ago> -there are glyphs composed from several codepoints (base glyph + combining accents), which should be treated as one "character" The solution is to use Normalization Form C (NFC) (which combines accents with characters). > there are ligatures that hold single codepoints, but which semantically are multiple "characters" OK, so use Normalization Form KC (NFKC) (which splits ligatures, and combines accents with characters). You're right that "length" of a unicode string is very ambiguous. Arguably, you shouldn't be able to call "length" without supplying an argument about what you are actually asking.
- cbhl 13y ago> explains that leaving out overloading is "simpler", meaning _simpler for them_. This also means your program code is simpler, and therefore, faster. Function overloading usually means virtual method tables, and therefore indirect method calls. Depending on how deep your inheritance / overloading structure is, these vtables can get really messy. (I had a class in university where we were given a C++ UML class diagram, and told to draw the vtables that resulted when one instance of a subclass was instantiated.)
- n1ghtm4n 13y agoFunction overloading can be accomplished by name mangling at compile time. PROGRAMMER SEES INTERNAL REPRESENTATION foo(int a, char b) foo_int_char foo(int x) foo_int
- lysium 13y agoHe did not mean overriding (methods in derived classes), but overloading (functions with the same name). You can resolve the latter at compile time, no indirection needed. For example you can have two overloaded functions println() and println(String).
- mratzloff 13y agoHave you spent much time in C? Go is directly descended from C, not Python. Its requirements are different. - If you are passing a number of related arguments, often a struct is a better data structure than default or named parameters. - I am ambivalent about panic/recover, but have no problem with the rest. - I do tend to agree that "and" and "or" would be more readable, but it's such a minor issue. - Regarding your UTF-8 example, I imagine the Go authors believed most Go users would be spending more of their time dealing with bytes than characters. Go is not a language optimized for text manipulation, it is optimized for byte manipulation, like C. This is apparent in the lack of effort put toward optimizing the regular expression engine to date.