Hacker News new | past | comments | ask | show | jobs | submit login
Go generics may use square brackets [] not parenthesis () (groups.google.com)
172 points by psxuaw on July 15, 2020 | hide | past | favorite | 314 comments



Why don't they just use characters from the Canadian Aboriginal Syllabics block?

https://www.reddit.com/r/rust/comments/5penft/parallelizing_...


Every time I click a Reddit link I'm astounded about how bad & user-hostile the new UX is.

Old-style link: https://old.reddit.com/r/rust/comments/5penft/parallelizing_...


If you have an account you can set the old style as the default. No email required to sign up even though they sort of make it seem one is, just hit next.


I use the Redirector addon to deal with other stuff, so it also helps without having to set up an account anywhere


The new UX is terrible, but note you can still minimize comments by tapping the white space to the right of the username. Horrible discoverability, but at least that is still there.


Ha! I didn't even notice the lack of [-] signs! I guess I never had a big need to do that...

Actually my biggest complaint is the lack of ability to maximize comments - basically, I detest having to click n times just to be able to read the whole discussion. There's a bit of content, and mostly SPAM on that page. Old design was mostly content.


I had to blink a couple of times and then google it to verify it wasn’t a joke. Wow.

To quote my favorite mathematician specializing in chaos theory, ”Your scientists were so preoccupied with whether or not they could, they didn’t stop to think if they should.“


> type ImmutableTreeListᐸElementTᐳ

> If you look closely, those aren't angle brackets, they're characters from the Canadian Aboriginal Syllabics block, which are allowed in Go identifiers. From Go's perspective, that's just one long identifier.

And the next comment is the same thing everyone else is thinking: “oh my god


I also like this comment from the almost-empty /r/ProgrammerHumor/ submission linking to that thread:

  Gives new meaning to the phrase "Native apps"


To be fair I suspect this part of that sentence explains the reason for choice of these special character:

From Go's perspective, that's just one long identifier.

The designer was using those characters to trick the Go compiler which I then suspect means things like go format would also continue to work.

Then the designer could easily create a pre-processor that translates those placeholders characters as a way of providing some sort of generics in Go.

So in reality this was quite a good solution as I can imagine coming up with a solution that broke go format would have been a real pain to use.


> So in reality this was quite a good solution

Yes, I do not understand why people find this so hilarious. It's a clever choice.


Because they look like normal angle brackets. Unless you are in on the secret, you won’t understand why your code doesn’t work.


Easily fixed by using ᑅ ᑀ, ᕙ ᕗ, or ᗕ ᗒ.


For some values of "easily" and "fixed".


Maybe it’s just at the companies I’ve worked at, but replacement vars are usually double underscores:

    Here is __REPLACE__ var.


That is a clever choice.

A wise choice would be simply adding double underscores between the identifiers.


The fact that the author needs to explain how it works on an Internet forum is evidence it was neither a clear nor clever choice, but a probably a bad choice.


Clear is better than clever.


I like to know this:

> c++ allows 0-width spaces in variable names. Where's your god now?

I imagine many languages do the same, but I lack the will to test it.

Anyway, of course, it would be more correct if it was considered whitespace... And I bet anything parsed in Haskell or Perl6 does such.


See: https://go.googlesource.com/proposal/+/refs/heads/master/des...

> Why not use F«T»?

> We considered it but we couldn't bring ourselves to require non-ASCII.


Terrible idea, it would break that person's use case.


IIRC these characters are also used in the reference implementation from the proposal authors, of course.


>A typical computer keyboard provides four easily accessible pairs of single-character symmetrical "brackets"

"falsehoods programmers believe about keyboards"

On the keyboard layouts of many countries these keys aren't accessible at all, either missing entirely or only being accessible via unergonomic key combinations.

For this reason myself (and many other programmers) own additional ANSI-US layout keyboards.


QWERTZ here. I need to use the following key combinations:

shift + 8 -> (

shift + 9 -> )

alt + ctrl + 8 -> [

alt + ctrl + 9 -> ]

alt + ctrl + 7 -> {

alt + ctrl + 0 -> }

Alternatively alt + ctrl can be replaced by altgr.

And for further fun:

alt + ctrl + ß -> \

shift + 0 -> =

shift + 7 -> /

Actually, it is probably easier to link the whole layout: https://de.wikipedia.org/wiki/DIN_2137#/media/Datei:Deutsche...

It is pretty bad for programming in languages that make heavy usage of braces/brackets/parenthesis.


> Alternatively alt + ctrl can be replaced by altgr.

What operating system are you on? I can only create those with AltGr, anything shift-alt will be interpreted as a keyboard shortcut.


Win 10.

Are you maybe confusing alt ctrl with alt shift? Your comment seems to indicate it as that being the case.


That's why I switched to Qwerty 20 years ago (from Azerty); I used caps lock as a compose key for diacritics. Makes it easier to type common signs such as ≤ → ≠ Ø


Same here, I only use US layout, but caps lock mapped to compose the keys my native language needs. They are mapped to the same place I left them 10 yrs ago, it was easier the beginning.


at that point, you might as well buy a QWERTY keyboard


I have a QWERTY keyboard but with italian layout, and the special characters are also in different places[0].

I have

* <shift>+<8,9> for (,)

* <altgr>+<è> for [

* <altgr>+<+> for ]

* <altgr>+<shift>+<è> for }

* <altgr>+<shift>+<+> for }

yes, it's a pain to use some languages.

[0] https://en.wikipedia.org/wiki/QWERTY#Italian


Add to that the fact that typing ~ and ` is impossible with the standard it layout (on X11 you can using platform-specific extra key combinations, such as `AltGr` + `+` if I recall correctly, while on Windows you must use ALT codes). So pleasant...

Also, random rant, the IT keyboard layout is moronic because on most platforms inputting accented uppercase letters is not possible in any way. Ironically, 'c with cedilla', section sign `§`, degree sign and the now unused pound sign are present on every key and easily typed using shift.

I've been arguing since the dawn of time that "US with dead keys" is a vastly better keyboard layout for Italian than the Italian one, and that's the one I use (more correctly, I use US International with AltGr keys due to the fact I type accented letters less frequently than I type single quotes or backticks).


Everyone in our field should do themselves a favor and learn to touch-type regardless of the physical keyboard.


I agree, but this doesn’t has anything to do with the keyboard layout, except that if you need to switch layouts regularly, touch-typing doesn’t get easier.

The thread is about the accessibility of some brackets on German QWERTZ keyboard layouts. These curly brackets aren’t even printed on some external Apple keyboards. And if you try to type them with one hand, you would need to turn your wrist in some unnatural position. That’s the main reason why I use an US QWERTY keyboard for the last 15 years.


Umlaut vowels and ß are easy to input using the US international keyboard layout (with dead keys/AltGr combinations). I'm Italian, I study German and I find extremely convenient being able to easily input both àèéìòóù and äëöü without having to learn a second layout and switching.


I am quite a good touch typists and that makes it so difficult for me, to switch layouts. Once your muscle memory is hard wired, you cannot arbitrarily change things. Last time I had to type on English layouts, it reduced my ability to touch-type greatly.


Well that's exactly my point. Pick a layout and stick to it. Regardless of what's printed on the keys.


Right, that's what I did. I stuck with the German layout, as this allows me to use my native language too. But his means, certain characters, like brackets, are more difficult to type and thus the assumption, that everyone is using an (US) English keyboard is a wrong one.

But in a general sense, I fully agree to your statement. Learning to touch type was an extremely valuable skill to acquire and I can only recommend it to everyone.


I did a few years back during uni[1] and I'm pretty sure that's still my most used skill I learned there.

[1]: Decided one day to get myself one of those little booklets with training software on CD. I then slowly stepped through the training steps (each step more letters and more repitition of already learned ones) and got decent at touch-typing by forcing myself to use it more and more in everyday uni life. Took about one or two months to get up to a level usable in general typing (writing for reports/homework AND programming) with little to no pauses or errors.


This doesn't help with some of the difference between ANSI and ISO layouts. For example ANSI uses a long Enter key while ISO uses one that looks like the shape of a "7".


ISO has one extra key, that's it.

I only buy ANSI keyboards and like the layout better (both Enter and left Shift are easier to reach) but I occasionally get to type on ISO keyboards, it's not too bad.


I tried to learn the qwerty layout before, but my muscle memory is so ingrained that it was impossible for me at the time.

And without correct keycaps it is even harder.


About 11 years ago (I think) I switched to the Colemak layout. It's a pain to switch at first but you do quickly get used to it.

That forced me to always touch type, a good thing. It also has the advantage that the layout is pretty consistent across physical keyboard layout.

That's not the case for UK Qwerty; UK Apple is different to UK ISO is different (obviously) to ANSI. Where as Colemak is pretty consistent. So it's been helpful when moving between machines and OSs.

...it's also been the generator of hilarious memories, such as when someone changes their layout to Colemak for me to type something and then we logout their machine and discover they can't type their password or change layout back to Qwerty. Ah, good times...


Not being able to look at the keyboard is actually a good way to learn.

Of course you'll have to fight your muscle memory and type at 20 wpm for a couple weeks. There's no shortcut.


My problem is that I need to be able to check where the keys are to be able to learn it in the first place. I can touch type quite well, just not type at all in a layout I never used before, without being able to look at the keys.


Print out the layout and put it under your monitor while you learn.


That is such a good idea that I missed it for being so simple.


I seem to be unable to find qwerty keycaps for a g513 without having to buy a completely new keyboard. So, for me it is not really an option.


Inspired by the space cadet keyboard, I have (){}<> as hold/tap on my modifiers. It vastly improves my coding experience.


Are parentheses not used in daily writing in your language?


DE shift+8/9 is only slightly worse than US shift+9/0 for parens. Brackets+Braces are the real problem on DE layout. I switched between US (programming) and DE (writing German) for a couple years; but then ended up using US-intl-no-dead-keys everywhere because the constant switching of input methods was annoying (especially due to Y/Z being swapped on DE, which causes confusion between undo/redo).


They are, but so are ä, ö, ü, Ä, Ö, Ü, and ß.


I don't think this is very notable since these brackets are already present in Go and almost every other language.


Yes, they are, and for me they are distinctly more difficult to type than parens.


I typically use French Canadian layout keyboards, and quickly switch to US with Win+Space when programming and switch back for regular typing.

I never felt like owning a new keyboard was necessary as a memorized the keys fairly quickly. The CA-FR layout is QWERTY+accents, but () {} etc. are weirdly placed, some requiring the use of the “alt-car” key which I’m not even sure exists in the US layout. I really hate programming or using vim in that layout.

Are there layouts where that approach isn’t feasible? Or is it mostly a memorization issue?


>Are there layouts where that approach isn’t feasible? Or is it mostly a memorization issue?

You can adapt most of the western layouts to at least get "[]{}" in easily accessible places, but for instance trying to adapt a German layout can get really confusing. Have a look at this typical German layout:

https://upload.wikimedia.org/wikipedia/commons/thumb/3/36/KB...

So we can remap "{}[]" to somewhere next to the enter key, ideally by moving the "+" key to the upper row. We also want to remap "|" and probably "<>" somewhere next to the enter key, because typing those a lot also gets awkward in their former spot. You could compensate by the entire bottom letter row to the left, arriving at something close to US-ANSI.

Needless to say, that's going to get really confusing. I'm a touch typist, but if I'd already have trouble, I don't want to imagine what that's going to be like for someone who is not.

Personally I just use an ANSI-US layout keyboard with a few custom shortcuts for typing ä, ö and ü. I can get away with this because I don't need to write a lot of German text.

For someone who has to switch between layouts to be efficient in both writing German text and code, it's probably better to use physically different keyboards so it's easier to build muscle memory.


I'm originally Swiss, so I use the Swiss keyboard layout, which is much better when it comes to bracket placement: https://commons.m.wikimedia.org/wiki/File:KB_Swiss.svg

Except on a mac, because for some reason the mac layout is totally different, which is why I need to use a key remapper on my work computer.


I guess most European languages with Latin letters "with adornments" can be written quite nicely with a keyboard layout similar to US Intl.

You can write the characters using digraphs.

For example, type <"> and then <a> to get <ä>. Type <"> and then <space> to get <">.

This won't work for other alphabets, of course.

Not sure what CJKV users do.


> Not sure what CJKV users do.

Chinese: the physical layout is always ANSI US. Depending on the IME you might want more than roman characters printed on keycaps, but it's just cosmetic if you can touch-type.

Japanese: most keyboards use the JIS layout and visually support multiple IME, but if you stick to romaji, using an ANSI US keyboard works too.

Korean: the physical layout is ANSI US (sometimes with 2 extra modifiers). Hangul is a proper alphabet, symbols are made up of subcomponents (jamo) that are printed on the keys. Again it's just cosmetic.

In my experience, people of my generation (30-40 years old) who are educated know to touch-type. For instance I've never met a Taiwanese that needed to look at the Zhuyin symbols on a keyboard.

But I've heard that's not the case anymore with kids that grew up using smartphones.


Just to expand on this, at least in Mandarin, one types out phonetic Latin alphabet-based pinyin and the system prompts you with choices of matching symbols in the same way that predictive keyboards show you words. You select which characters to insert by clicking/tapping on them or hitting a number key. The only big difference is that the same pinyin might correspond to any number of characters and you might have to search through a lot, but context and frequency helps it suggest the right ones to you. (Mandarin only has 409 different pinyin 'syllables' when ignoring tones, which aren't typed in this system. Even with tones, there's only like 1200. These map to many thousands of characters, obviously not one-to-one. Depending on how you count, English has something like 16000 syllables.)


Works pretty the same in Japanese, they just have their own syllabic scripts (two of them), but the entry method can support them as well.


Based on the pinyin based Chinese input method I've seen, I guess the user will want to switch to US for entering code, right? Otherwise, the IME will offer Chinese characters...

What I like about using US Intl (I've modified it slightly) is that no switching is required, I can conveniently enter both the programming related characters (such as curly braces which require gymnastics with a German keyboard layout) and the German specific characters such as umlauts.

But I can't imagine that this could be possible for Chinese without switching modes (or input methods or keyboar layouts).


Why not switch between US and US international? No need to learn two layouts and where accents are located.


We all learn to type on CA-FR keyboards, so using US-INT would require me to learn yet another layout for accents. Plus CA-FR is the one actually printed on keycaps everywhere; using US-INT for accents would be counter-productive.


Or use US international without dead keys. No need to switch when you can just use right alt for the non-ASCII characters.


Cases where ` 's are used for quoting are a big example of this. Typing `example` turns into èxample` on my keyboard because the backtick key is a modifier for the next press. To type `example`, I need to type:

* On Linux: ``example`

* On Windows: ``<left>example

Some editors even turn the latter into ```` when I double press the backtick as no symbol renders prior to that.


at least for windows you can change the keyboard layout to directly output the deadkeys, example for german: https://github.com/RAnders00/Deutsch-ohne-Tottasten

if none is available for your language you can build it yourself: https://zauner.nllk.net/post/0014-windows-no-dead-keys/


This struck me too. Writing code on an Icelandic keyboard is an awful experience.


Looking at the Icelandic layout[1] from a programmers' perspective, the big difference appears to be that \, [, and ] need a modifier, Alt-Gr; and ; (semi-colon) is shifted.

The shifted semi-colon must be irritating in C-like languages, but even on US/UK keyboards, characters like ( and { need Shift, which admittedly is larger than Alt-Gr and there are two of them.

I wonder if the larger right Shift key can be mapped as Alt-Gr.

PS. Does Icelandic need the letter 'mu' often enough to dedicate a key to it on the keyboard?

[1] https://en.wikipedia.org/wiki/Icelandic_keyboard_layout#/med...


μ is used a fair bit by anyone who uses the metric system, so it makes sense to include it. It's used as a prefix to denote a millionth for those that don't know, as in µm = micrometer = a millionth of a meter.

It's mapped to Alt-Gr+M on Swedish keyboards as well, but I've never seen a keyboard where it's actually written on out on the key.


> A fair bit by anyone who uses the metric system?

I'm sorry, but what?

Most people who use the metric system can't tell you which is smaller: micro or milli. Most people will never encounter anything in their lifetime they will actually need to reason about in some important manner that is measured in μ-anything.

As a user of the Icelandic layout I wasn't even aware that the key was on there, but I can confirm that we absolutely don't need it. I think there are probably a lot of keyboard layouts that could use modernizing wrt. how they are actually used today.


µ would be used by scientists, engineers, doctors and nurses.

That doesn't seem unreasonable, when we have <, >, { and } for mathematics, \ originally for logicians (to combine to make /\ AND and \/ OR) and |, @, _ and # for programming.


Shifted semicolon is absolutely a non-issue. If there are any problems with the layout, it's hiding the symbols behind altgr, but the shifted semicolon is really not a problem.


I think if my mother tongue wasn't English, and I therefore regularly typed on a different European layout, I'd remap the left Windows key or maybe Caps Lock to be an additional AltGr.


I disagree. I have been writing code with the icelandic layout for over 20 years and it has really never been an issue for me. You put your right thumb on altgr and hit the number keys.


I think it is reasonable that programmers should be able to modify their keyboards to have easier access to useful keys, ie all the caps lock-esc stuff.

Btw, Microsoft Keyboard Layout Creator is a terrific tool. I spent around 10 minutes sω tφαθ İ cöüλδ tyπε lıκε δiş. (Turkish characters accessible through AltGr and Greek characters accessible through a dead key) And if you look at the config files (some kind of tab separated values with comments), the created keyboards are easily sharable and combinable.


> For this reason myself (and many other programmers) own additional ANSI-US layout keyboards.

Why though when you can change layouts without changing keyboards.


Several reasons (I'm not op).

The main one is that you might not know the placement of the keys of the US layout by heart so having your printed keyboard match the layout is best. I'm a touch typist, but I still look from time to time to find things like | or ~.

Also, your physical layout might be slightly different, then finding the right key becomes a matter of trial and error for some edge cases (think the inverted L shaped enter key vs the long rectangle version).


The last point has nothing to do with the language really. At least not the shape of the enter key. On Nordic layouts you usually have an extra key left of Z for angle brackets.

There really is no reason to switch between actual physical keyboards to use a different keyboard layout, even if you need to look at the keys(and it would still require you to switch layouts in software). Surely googling a layout cheat sheet is easier than switching keyboards.


> There really is no reason to switch between actual physical keyboards to use a different keyboard layout, even if you need to look at the keys(and it would still require you to switch layouts in software). Surely googling a layout cheat sheet is easier than switching keyboards.

In my case, more than switching, it's that my laptop has a spanish set (work provided), and I went through the trouble of buying an external one with an English layout. It's not like I'm switching between them every few minutes, the Spanish one is left unused. I don't even bother switching layouts, since I can perfectly write Spanish with the English layout (the only missing keys are accents, which I omit in informal texts, and the ñ key that I can get long pressing the n).

I could use the Spanish one and look at a cheat sheet from time to time, but it's inconvenient enough that the 40 extra bucks feel like a good inversion.


Programming is almost always conducted in English, even if the application itself as well internationalized and can be used from different languages. Even API documentation is almost always written in English regardless of the country of origin of the author. The only exception I can see to this rule is programs and docs written in China.

Everywhere else, it's reasonable to assume that if you're a programmer, you speak English and likely have an English keyboard. This may not be fair, but it is the state of affairs.

You likely own a US keyboard not only for the parentheses problem, but because of all sorts of English isms throughout all code -- alphanumerics, urls, etc are all in Latin script. It's like German in the field of mathematics in the 19th century.


It's reasonable to assume that you speak English, but not so reasonable to assume that you have an English (US or UK, for example) keyboard. Basically all of us have keyboard with Latin letters, that are perfectly up to the task of writing "normal" English, but the seldom used braces and brackets are behind some alt-gr shenanigans.

Yes, they are symbols that are used in many programming languages. No, it's not reasonable to assume that they are easy to type for all of us.


I don’t get your issue with modifiers such as alt-gr. I grew up with a mix of Swiss (swiss qwertz) and French layout (azerty), and have my own custom layout since around 10 years, all of them require to use modifiers just to write my main languages and that hasn’t been an issue since I was a kid. If you use a non US layout it’s very likely that you already use modifiers quite often, I don’t understand why that would become an issue once you start writing code.


It is reasonable to assume that anybody writing code is using the US keyboard layout. That is the de facto standard and standards are important.

Anybody who deviates from that is doing so at their own risk. If you want to use Dvorak or Azerty instead of Qwerty then you can do that, it's just not advisable because things like Vim will no longer make sense.

If you try to write code using a layout that doesn't have all the ascii printable symbol characters in accessible locations then you're creating a special kind of hell for yourself. It takes like 30 seconds to change to US layout.


> It is reasonable to assume that anybody writing code is using the US keyboard layout. That is the de facto standard and standards are important.

That’s not reasonable at all. You have way more people writing code outside of the US than within. The US layout may be the most represented one, I don’t know statistics on this, but I would expect it to be on the losing side when comparing US layout vs non-US layout.

Though I would agree that having access to ASCII is something you need, but any standardized keyboard layout in the world can do that via modifiers, if not directly.


Its reasonable in the sense that the decision was already made, by history & circumstance, and that it's largely not that problematic and well supported (out of necessity).

The only alternatives would be to converge on a lowest common demoninator, and have a likely more inconvenient syntax for all parties, or to diverge into regional-specific dialects, which unicode shows to be.. wide.. and generally make code sharing much harder.

This is really more of a "many mostly equivalent solutions, but one needs to be picked" scenario -- and it would be time poorly spent trying to undo the incumbent solution (and will naturally be rendered untenable by endless bike-shedding anyways). The worst of all solutions -- except for all the others


Lots of non-US based programmers use a US layout anyway though, so I think it's a pretty reasonable assumption in the context of English language programming


No, it is not reasonable. While, as you can see, I am fine using English, I have to use a German keyboard layout because otherwise I would lose the ability to type my native language.


There is nothing preventing you from swtiching layouts between coding and typing German.


Yes, there is: I am a touch-typist. So the layout of the keyboard is wired into my muscle-memory. Trying to switch layouts wrecks havoc with that. I tried it for a while, when I had to use an English layout at work, and it was very detrimental to my typing abilities. So I had to decide on one layout, and my native tongue won. As you see, I can type English text quite fine, just the brackets are more painful to type than parens.


How long did you try? Of course learning to touch type on a different layout will take some time but that doesn't make using brackets in programming languages unreasonable.

Using a German layout is very much a choice you have made and is no reason for you to demand that programming languages should make everyone else's life harder to acomodate those choices. Even for German text input, umlauts and sz are rare enough that it is not much of a hindrance to have to enter those via dead keys or compose sequences on a layout that doesn't make {} and [] a pain to type.


I don't think that's reasonable to think at all. Literally no one I know locally that is also a programmer uses the American layout. The difficulties of inputting symbols with ex. altgr is overstated.

I really don't think most people use the American layout. That's just typical america-centric narcissism.


I speak Swedish and code/message/email in English for work, but I still need to type Swedish occasionally so my keyboard is Swedish both in hardware (layout) and software (mapping).

Curly brackets etc use hand-twisting alt-gr combinations on a Swedish layout so I’d be better off using a US keyboard mapping so I can type ([{ using only shift. I have tried and failed to make that switch. It would probably just slow me down for a month or so before it made me faster, but I’ll keep pushing my square-wheeled cart thank you.


I have tried too and I gave up. It made my head hurt and you are not really getting the US layout anyway.


I created an Emacs minor mode to make the ö/ä keys type square/curly brackets, but it’s not ideal.


Unfortunately this is not the case. Many, many people use laptops, and getting laptops with non-local keyboard layouts is Really Quite Difficult. You usually have to go to the place where the layout is native to buy it.

External keyboards, sure. But many of us are laptop-only.

Sure, you can remap the keys, but also, not everyone is a touch typist.


Even if your code is written in English, some text still has to be written in your own language (in particular, anything the end user will happen to read). And, although you can write English from a (say) French keyboard, writing French from an English keyboard is a PITA.


> writing French from an English keyboard is a PITA.

There's no English keyboard.

Writing French with the US international layout is actually pretty easy.


There are US English and English UK keyboards, both a very similar, and very dissimilar from French and German keyboards. I would challenge you to tell me how you type the following letters "easily" on an US international keyboard: ä ö ü ß.


https://en.wikipedia.org/wiki/British_and_American_keyboards...

The umlaut is a dead key so it's very easy. ß is AltGr or Option + S which I admit is a bit more annoying, but your spellchecker should take care of that, no? (I'm Swiss so even when I have to type in broken German, we don't use the ß here).

All layouts are tradeoffs. Not using the US layout makes a lot of things annoying in our field. I write code and use my IDE's keyboard shortcuts more than I need to write long texts in my native language.


There are many diacritics in French, and not having a key for the most frequent accentuated letters is far from optimal (for instance, the previous sentence in French would contain 5 diacritics).


You'll never find an optimal layout, they're all compromises.

I've switched to US intl 15 years ago and I don't type in French any slower than I used to. On the other hand I benefit greatly from using the default layout in our very US-centric field.


If I set my layout to US then @ and " swap.

So " is Shift+' and @ is shift+2

In UK keyboard layout, @ is shift+', and " is shift+2 (which is what is shown on my keyboard keys).


Can you imagine how Russians and Bulgarians deal with it? Yes, they switch layouts all the time. Write some lines of code in English, switch to Russian or Bulgarian to write comments or reply in Slack.


No, it is not reasonable to assume that people, who are fine at speaking English, are using an English keyboard layout. I am using a German keyboard layout, as I want to be able to use my native language, and that is not possible with an English layout. However, as I am a touch-typist, I cannot switch keyboard layouts frequently, so I have to go with the German one.


I can touch-type in Russian and English layouts.

My favorite keyboard is British up to the point of me specifically picking a laptop/physical keyboard with a British layout.

Just learn both and you'll be OK.


Lucky for you, that you managed to learn to touch type on the different layouts. It might help though, that Russian and English are entirely different layouts. The problem with German and English layouts is, that they are mostly identical, and only about 10% of them differ. This makes it very difficult to master both layouts at the same time. I tried it for a while, when I had to use an English layout temporarily. My experience was, that it thoroughly made my typing worse on both layouts.


I've got friends who used the phonetic version of Russian keyboard where about 80-90% of the letters are going to be similar phonetically. All of them can touch-type by now.

The thing with touch-typing is that you don't think so you have to go through a period of discomfort.


I am very proficient with touch typing. But in my experience, mixing German and English keyboards erroded my skills considerably.


I regularly switch between American and French layouts. I don't think it's particularly hard.

Edit: If that wasn't clear, I meant that I touch-type on both layouts quite easily.


I've long desired a language that uses only alphanumeric characters and whitespace with minimal punctuation. Kind of a cross between Haskell and Delphi.


TIL! Does your default keyboard have the usual round parentheses?


They probably still exist but harder to type/require some kind of key combination. The reason to move them is not because they are not used (although in some languages probably it is) but they are less used than the additional characters in those languages


At least you can use gucharmap or other unicode lookup tools to get those characters


You can't please everyone. So might as well pick the most common keyboard layout among your users and call it typical computer keyboard.

I'm afraid there's no easy solution to this problem but I'd like to hear your suggestion.


Well, there's always

   begin
and

   end

Isn't there? ;)


Or… indentation! crowd gasps; lightning flashes; thunder claps; maniacal laughter is heard in the distance


generics with begin and end?


Well, Haskell uses just a space.


I think Ada does something like that (type T is array of I with E) but yeah, I wouldn't advocate that :)


There is no easy solution to the problem, so no one should pretend there is. Yes, if I program in Go, I have to type square brackets [] from time to time for slices. But for me it is more painful, so I strongly prefer the generics notation with parens ().

It may be, that in the end the parens are the solution to use, but at least it should be considered in the discusion, that they are not very easy to use for a lot of non-English layouts. Just assuming anyone in the world would use an English layout, is quite offensive in my eyes.


>On the keyboard layouts of many countries these keys aren't accessible at all, either missing entirely or only being accessible via unergonomic key combinations

Not really relevant, as we're talking about keyboards and setups used by programmers.

If they don't know how to change the layout in English to program, then perhaps they're not fit for the job.

(Non ASCII/US programmer here).


Except there is this little thing called documentation and user manuals that one has to write on our native languages, yes even code comments.


There's this little thing called Alt+Shift.


Indeed, doesn't make any less painful, though.


I really like the syntax used to declare generic type parameters to functions in ML-type languages like F#.

Writing the below in other languages (pseudocode) feels repetitive in the same way that `Thing thing = new Thing()` did back before `var` or `auto` types became popular:

    list<Y> Map<X, Y>(list<X> inputs, X->Y mapping)
Why do I need to put <X, Y> in brackets after Map? To tell the compiler that these are generics, not attempts to reference actual specific types that just happen to have crappy, nondescript names like X and Y.

In F# and friends, there is no need to put a bracketed block declaring which types are generic parameters. I would simply write:

    let map (inputs: list<'x>) (mapping: 'x -> 'y) : list<'y> = ...
The little apostrophe or tick mark before the type name tells the compiler it's a generic type parameter. It's not legal to name a concrete type with a leading tick mark, so there can be no mix-up. At first it looks ugly, but once you are used to it, it is natural and less cluttered than having to have these separate bracketed declarations for "uh-oh, here comes a generic".

But I suspect Go will always want more explicit syntax for generics. In part out of backwards compatibility, but largely because Go's designers see generics as an advanced, occasionally useful feature. Correspondingly they'll want the presence of a generic function to have ugly syntactical warning signs: here be dragons.

Functional languages usually take the opposite approach and see a fully generic function as less complex than one for a specific type, because just by looking at its signature, you know it doesn't require anything special about the input objects it's going to work on. It is not going to be calling methods on them or messing with their guts. It's just treating them as black-box, could-be-anything cards to be shuffled around from point A to point B.


> Why do I need to put <X, Y> in brackets after Map? [...] In F# and friends, there is no need

Try:

  let foo (arg: list<'x>) : list<'x> =
    ...
    <inside foo somewhere>
    let bar (arg: list<'x>) : list<'x> = ...
    ...
Is bar generic over a fresh type that happens to be named 'x, or is it a monomorphicly-typed local function that uses the type 'x that foo is generic over?


not sure about F#, but in haskell it's the former, and you can switch to the latter with the -XScopedTypeVariables language extension. though IME you rarely (if ever) need it thanks to type inference.


Actually, on further consideration, you could restrict the ' to only occur where the type parameter is introduced, like so:

  List<X> foo(List<'X> inp) =
    ...
    List<X> bar(List<'X> xs) = ... # new X scoped to this declaration
    List<X> baz(List<X> xs) = ... # use foo's X
    ...


That's only possible because F#'s (and OCaml's) type system is so simple (basically the only possible relationship is equality, with is indicated by reusing the same letter twice). But if your system is more complex, even like Java's, you often need additional constraints, e.g. <X : Hashable> or something. In that case, you probably do need to declare your type parameters.

Best, of course, would be some middle ground assisted by a fantastic compiler.

    group_by : list[`a] -> (`a -> (`b : hashable)) -> Map[`b, list[`a]]
or something


> you often need additional constraints, e.g. <X : Hashable> or something

in haskell:

  noConstraint    :: List a -> (a -> b) -> List b
  withConstraints :: (Hashable a, Frobable b) => List a -> (a -> b) -> List b
you still don't have to declare `a` and `b`, you're just adding a constraint on them.

(iirc in haskell types have to start with an uppercase character, which means you can use lowercase letters for type variables without extra apostrophes etc)


Indeed! You could use other chars if the single quote is a problem.

Make identifiers that start with period or tilde perhaps be used for template vars. And only template vars. Might be a bit noisy but less noisy than reusing various types of braces.


If you want to indicate they're parameters you're probably best of using syntax that's already being used for parameters like, $a, ?a, :a. I guess {a} is also used, but we wanted to avoid braces.

Not sure if .a or ~a are good choices. The latter is especially bad since it clashes with common syntax for "(bitwise) not a".


To me, Go feels condescending to write without generics. I may just not groke the idioms - but putting users in a walled garden that the standard library has the privileged to escape from (i.e. (Map<k, v>)) just seems to go too far in not trusting the programmer. The fact that generics have taken so many years - to still be talking about what [<( to use is beyond me.

There is a difference between becoming C++ and allowing programmers to make fundamental abstractions without interface{} hacks.


The problem is not so much the absence of generics but the availability of crazy reflection at runtime compared to the rigid type system at compile time. There absolutely is a lack of balance here.

All these things were already pointed out 10 years ago and were met by "you don't need that with Go", "Go back writing Java" sort of contempt, which gave the Go community a bad reputation.

Go could have been fixed 10 years ago if Rob Pike and co listened. They didn't want to because they thought they knew better than everybody else. ADA already fixed the genericity problem while keeping things readable with a limited form of generics as incomplete types.


As I already mentioned a coupled of times, even CLU like generics would have been a good enough solution.

Something that they acknowledged not bothered to look at initially.

https://go.googlesource.com/proposal/+/master/design/go2draf...

> We would have been well-served to spend more time with CLU and C++ concepts earlier.


Well said. As a C++ programmer I always find Go rubs me the wrong way. Like they want to make my life difficult. I think you hit the nail on the head that it feels condescending. My visceral reaction to not being able to write a standard library as performant as the provided one is “this is a toy language”. I know it’s not and I know I have to use C to do that in Python, but still.


Maps are part of the language. The standard library is written in Go. There are a few special packages (unsafe, reflect, ...) but maps are not one of those cases.


> A typical computer keyboard

A typical NORTH AMERICAN computer keyboard.

Does the myopia of the Go compiler team know any bounds?


Nope it does not!


You mean a typical English keyboard?

Ironic that you are criticising them for only thinking of the US, but you've done exactly the same thing.


The ISO UK keyboard layout exists. The North American keyboard layout is North American, not "English".


This is true, but an ISO UK keyboard also "provides four easily accessible pairs of single-character symmetrical 'brackets'"; for this particular purpose there is no distinguishing factor between the two layouts.


There are other layouts in North America, including French (Canada), Bilingual (also common in Canada), Spanish (Mexico). Plus a multitude of people who have other preferred layouts. There is no official layout for this landmass.


They are identical when it comes to brackets.


I wish they would just freeze the language and not add anything. I like it the way it is. I feel like the general attitude of software developers is: if it isn’t changing and being updated it’s dying. I think we should start putting weight on stable unchanging software.


Let's be fair, they held out against a very vocal community for a very long time.

They used that time to carefully evaluate the utility and ethos compatibility of generics. And they're taking time thoughtfully implementing them.

This is what you want out of a language. Thoughtful design and responsiveness.


And I bet that if Go ever gets generics, they will look extremely similar to everything everyone has been telling them for years, even though they dismissed that feedback for years as silly.

The switch from parentheses to square brackets is just the first step toward that admission.


Something interesting happened when comparing the history of systems programming languages from the early 60s, throughout the 70 and 80's.

The resistance of C's design adopting anything that was already considered good practices in designing secure OSes outside Bell Labs, has a very familiar feeling.


It's amazing how we got here... Your comment immediately reminded me of Tony Hoare's Turing Award lecture (https://www.cs.fsu.edu/~engelen/courses/COP4610/hoare.pdf) which contains (among other fun/depressing gems to reflect on) a bit on the obvious-even-to-customers sanity of avoiding core dumps or worse due to a lack of bounds-checking.

"A consequence of this principle [of security] is that every occurrence of every subscript of every subscripted variable was on every occasion checked at run time against both the upper and the lower declared bounds of the array. Many years later we asked our customers whether they wished us to provide an option to switch off these checks in the interests of efficiency on production runs. Unanimously, they urged us not to -- they already knew how frequently subscript errors occur on production runs where failure to detect them could be disastrous. I note with fear and horror that even in 1980, language designers and users have not learned this lesson. In any respectable branch of engineering, failure to observe such elementary precautions would have long been against the law."


Yes, that is one of my favorite quotes. The key point is " would have long been against the law".

Until this kind of issue start suffering lawsuits, most companies won't change their behaviour.

Look at Microsoft, all the security speech, C++ Core Guidelines, improving .NET for low level programming, new founded Rust love, yet the Azure Sphere team decided to use C on what is supposed to be the Fort Knox of IoT security. A bit though story to buy. I imagine the Phonon layer has probably hardware memory tagging, but they aren't revealing what it does.


> everything everyone has been telling them for years,

Some generic obsessed people talking about generics is neither everything nor everyone.


This is a fair comment. Even the article we’re reading is basically the thought behind why square brackets is the best way to signify a generic. There’s mentions of parsers and that kind of design thought is important in a language.


The question would be how are they solving it differently after these many years. They are just following what every other language has done for the years. We agree on having that restraint is good, if they see it as not required.


> I feel like the general attitude of software developers is: if it isn’t changing and being updated it’s dying. I think we should start putting weight on stable unchanging software.

I agree with this.

However, the key is to stop once you've implemented the right set of features. Minimalism is about implementing the minimum necessary and no less. I firmly believe that generics are in the right set of features for a statically-typed programming language.

The problem is that Go has already implemented some features which clearly aren't in the right set of features--such as `go generate`--which already allow you to implement a crappy version of generics. So now you're starting to move toward the problem that C++ and (to a lesser extent) JavaScript have, which is that there are 5 different ways to do the same thing, which don't necessarily interoperate well with each other. If go were being implemented from scratch, it would be better to have generics and not `go generate`, but given the language already has `go generate`, there's certainly some downside to adding generics. It's not a simple choice.


The irony of go generate is that a similar approach was taken by C++ compilers back in the early days.

To give a proper example, Borland C++ 1.0 for MS-DOS had BIDS, so their own collections library with safe strings and vectors, as it happened with all major C++ vendors back in the day.

Well BIDS 1.0 used pre-processor tricks to generate the desired code, basically you would define the desired types and then include the data structure you cared about, and do this multiple times.

Eventually templates came into the picture and BIDS 2.0 shipped with a template version, based on the ongoing discussions at ISO.

We are talking about 1990 here.

As for the 5 different ways, that is the sin of the languages that start small as a counter movement without understanding that the others are complex not because it is fun to make them complex, rather because languages are products like anything else in software, and either they adapt to their customer base or they fade away.


The basic problem I see with Go is that its users are ignorant of how other languages have solved (or failed to solve) problems.

> As for the 5 different ways, that is the sin of the languages that start small as a counter movement without understanding that the others are complex not because it is fun to make them complex, rather because languages are products like anything else in software, and either they adapt to their customer base or they fade away.

Well, that's somewhat true, but there are two ways to adapt while avoiding the problem of having 5 slightly different and incompatible ways to do the same thing:

1. Pick a good set of language features up front and stick to them, devoting further development efforts to a strong standard library rather than language features. Example: Erlang.

2. Break reverse compatibility and remove things. Example: Python.


Agreed, although from the point of view of languages as software products, Erlang seems to be around just to support Elixir, and Python took an heavy bill by going that way.


"go generate" is an half assed macro feature that shouldn't even part of any modern language. Even C has better macro... And it has absolutely nothing to do with genericity, your argument is a fallacy.

If Go really wanted to be open, then Go designers should just have created a virtual machine and let everybody code their own language on top.

Go right now is just basically C with garbage collection. Only C developers love that, and Go designers are well aware that it is an hindrace to adoption in enterprise. The pressure to change seldom comes from the community at large, but Google itself and big corps using Go.


> "go generate" is an half assed macro feature that shouldn't even part of any modern language.

Agreed.

> And it has absolutely nothing to do with genericity, your argument is a fallacy.

In arguments against adding generics, it's been cited numerous times that you can achieve similar code reuse via macros. It's been a while since I looked at the awfulness of `go generate` so I'm not going to attempt to demonstrate the equivalency with that syntax, but here's how you'd achieve something similar to genericity with macros in C:

Instead of:

    T swap<T>(T* left, T* right) {
        T temp = left;
        *left = *right;
        *right = temp;
    }

    ...

    int a = 1, b = 2;
    char c = 'c', d = 'd';

    swap<int>(&a, &b);
    swap<char>(&c, &d);
You do:

    #declare_swap_function(T) T swap_ ## T(T* left, T* right) {\
        T temp = left;\
        *left = *right;\
        *right = temp;\
    }

    ...

    declare_swap_function(int);
    declare_swap_function(char);

    ...

    int a = 1, b = 2;
    char c = 'c', d = 'd';

    swap_int(&a, &b);
    swap_char(&c, &d);
So, macros do have something to do with genericity.

Macros are certainly a crappy way to achieve genericity, however, especially since the original reason go didn't include generics was to compile in a single pass, and adding a preprocessor adds another pass.

It's clear you were ignorant here. That's fine--I don't expect you to know everything. But I think it's reasonable to expect that if you don't know what someone is talking about, you approach the conversation with some humility and ask questions before accusing someone of a logical fallacy. Ignorance is fine, arrogance isn't.


> such as `go generate`--which already allow you to implement a crappy version of generics

The design document for "go generate" listed many motivating use cases, and not one of them was generics. The raison d'être for "go generate" is not to simulate generics. Some people just saw the character sequence "gener..." and made it about generics.


Meanwhile I will never use Go until it has generics.

I wonder if there is more of people like me or people like you...


To be fair I will probably not use it even if it has generics, at least not if I can avoid it. It will still have nulls, lack sum types, have messed up dependency management and so on. Though in times when I have to use (because it was not in my control), I would rather have them.


You summarised almost perfectly my gripes with Go. Thank you. Just to add one: any type has a "zero values" as a default value, and the compiler doesn't force you to initialize stuff. That single misfeature caused basically all of my grey hair, and I'm still young.


What do you like to use?


I'm not a stickler for any specific features: it's more about having a group of features that synergize with each other. So far I've not found a language that does this perfectly, but I've found a few that I think do better than Go:

1. Elixir: Pros: Erlang threading model is clearly the best I've come across, expressive syntax, strong data structures and algorithms in standard library. Cons: Slow for some things, anemic standard library for common problem domains, small community.

2. Python: Pros: Strong standard library for common problem domains, supplemented by a strong community set of libraries. Generally intuitive. Cons: Slow for some things, poor threading, inconsistencies in syntax, general dominance of configuration-oriented programming frameworks rather than libraries in the community, types are just not quite strong enough.

3. C#: Pros: strong type system, speed. Cons: dependency injection hell, MS walled garden.

I'd like to add Rust and/or OCaml, to this list, but I don't know either well enough to be confident.


>MS walled garden

.NET Core is FOSS though?


On paper, but it sure doesn't feel like it when trying to use it.

It's nearly impossible to find out which of the umpteen repositories contains the source for the class you're trying to understand, and MSDN won't be of much help. Much of the standard library also has a bunch of decoy source files that only contain signatures and/or mocks, so it's a pain to find the real version.

OmniSharp has a "go-to-source" option, but you only get the real source if it's in the same solution. Otherwise you only get signatures. Try giving Metals[0] or Rust-Analyzer[1] a shot, this stuff is night-and-day.

The official debugger (vsdbg) only works in VS and VSCode (and explicitly not in FOSS builds of VSCode). There is netcoredbg[2], but I still haven't figured out how to convince Emacs to use it. This wouldn't be as much of a problem if the culture wasn't so hostile to printf debugging (for example, ~nobody bothers to implement helpful ToStrings).

There is a heavy cultural bias towards MS libraries, regardless of their merits (ASP.Net Core, DI hell, EFCore, etc). See [3] for an.. interesting example.

OmniSharp has a habit of giving up randomly, giving useless error messages, and most GH issues consist of people repeating "+1", until there is a one-liner about how an update fixed it. Root cause analysis, what's that?

[0]: https://scalameta.org/metals/

[1]: https://rust-analyzer.github.io/

[2]: https://github.com/Samsung/netcoredbg

[3]: https://old.reddit.com/r/csharp/comments/9kha39/does_anybody...


> It's nearly impossible to find out which of the umpteen repositories contains the source for the class you're trying to understand > OmniSharp has a "go-to-source" option, but you only get the real source if it's in the same solution.

I have to admit I almost never run into this issue because because I don't really care what the source of the standard library does, the docs have always been sufficient for me. You could try https://source.dot.net/ though.

In the very rare case I do want to see the source of some 3rd party code I use dnSpy. It isn't as nicely integrated, but it's a very nice decompiler and debugger.


Hm, I didn't realize .NET Core had been changed to an MIT license. That wasn't the case when I was working in C# on a regular basis.

My guess is that MS proprietary tooling still sucks out the air from FOSS tools, but I can't speak from experience there so I'll just admit I don't know how the ecosystem has changed since I worked in it.


Visual Studio is definitely still the ideal environment for writing C#, but JetBrains Rider is a solid alternative, and VS Code with the right set of extensions is probably "good enough" for most things.


Rust is my favourite. I wish I could try Haskell, Ocaml or Erlang professionally sometime. I was OK with Scala, and would like to check Kotlin too.


Visual Basic, strict mode.


A language can't be everything to everyone. Given its age it is very widely used. So I'm not sure the lack of genetics is really hurting adoption. You run the risk of driving away existing users but not attracting people that already wrote the language off.

I say this as someone that doesn't use it for similar reasons as you. But I have ran into the above trap before.


I don't know, in any production system without generics, the code just looks amateurish...


The thing is, for people who want generics, sum types, non-nullability etc, there are plenty of other languages to choose from. For those who specifically want a simple language, Go is (was?) one of very few options.


sum types and non-nullability are not complex.


Sure they are. Sum types usually mean a pattern matching syntax, destructuring, and a different declaration syntax. Rust’s match keyword, for example, is a powerful construct covering guards, destructuring, and different types of binding. Non-nullability requires generics for a result type which is a huge source of complexity. Generics impact parsing, code gen and runtime efficiency.


1) Non nullability can be implemented in language without generics, and for all types instead of just pointer types. That can be used to enforce null checking with pattern like:

    if let var_name = nullable_var { 
        // use var_name as non nullable
    } else {
        // nullable_var in null, handle null case
    }
And any tagged union can be reduced to nullable of member type without pattern matching, with some specific syntax. It is not hard with an imperative language.

2) Without generics, you are probably reinventing the same code, or using reflection which is not even type safe, or worse, using code generation. For instance D has generics AND good compile times. I guess Nim compiles fairly well too. Or you can choose partially type erasure based generics with a different tradeoff. There is no point in not having useful generic functions on generic data structures in a language that came in 2000s.

Once write Python or ruby or something and come back to Go. People without knowledge of other languages with generics tend to think you are writing for loop in while loop in if - else break monstrosity because native compilation and performance come with a cost in expressiveness, while it need not be.


There is nothing wrong with code generation, what do you mean by "or worse"?


Off the top of my head: Poor error messages, any type checking is run on the generated code so harder to enforce properties, and if code generation is not in-language, then the base logic can diverge for different types, which is bad when you find bugs.


>Non-nullability requires generics for a result type which is a huge source of complexity. Generics impact parsing, code gen and runtime efficiency.

The C# 8.0 approach to non-nullability doesn't require generics at all (though C# already has a robust generic system). They just made reference types work the same as value types, add a ? if you want it nullable, otherwise it isn't.

I think Rust's way of doing it with Option is probably a better way, but C#'s way of doing it is definitely more accessible to the average programmer.


You could have a very simple `match` with no nested patterns or guards, like Haskell's core language.

> Non-nullability requires generics for a result type which is a huge source of complexity.

Option could be another built-in generic like Map in Go. Or one could simply have to write a new Option type ever time. Sucks, but aren't go programmers used to this sort of thing?

> Generics impacts runtime efficiency.

False


However go’s switch statement already acts like pattern matching and destructiving in order to support interfaces.


Given the Polls of go programmers have consistently shown that the lack of generics is a problem.


Where do I participate in those polls? I'd like to put my voice against.


As we all know, the only true value a programming language has is whether or not a majority of programmers align with its ethos.


Based on the popularity of the language alone, I can say rather definitely the latter.


I'm sure that being backed by the largest software/advertising company in the world has nothing to do with its adoption rate, and that popularity is a direct mapping of quality of a programming language.


The Google backing and hype kept me away from Go for years. After being stuck with a succession of scripting languages that weren't doing it for me and being frustrated at the time it takes to be as productive in something like c, Go is really the sweet spot of readability, reliability and productivity for me. I think the Google backing may not be as advantageous as some people think. Dart did not become a popular language and would probably have died out if Flutter hadn't come along.


Yeah, Go being from Google is not necessarily a good thing. It means the language is under the control of a single company and, what's more, a company that is well-known for giving up on many of its projects.


And the open-source aspect of Go's development is managed entirely in Google services (the dev mailing list is a Google Group, you can't contribute without a Gmail address...the list is long). Sure it's hosted on GitHub, but the majority of the real conversations are elsewhere.


> frustrated at the time it takes to be as productive in something like c

Don't worry, no is productive in something like c

> After being stuck with a succession of scripting languages that weren't doing it for me

I am saddened yet also consoled everyone that likes Go comes from the scripting languages. That's such a low bar to beat!


Yeah. That's why it's about as successful as Dart.


I guess the political wars of JavaScript vs Dart, ChromiumVM and Chrome team dropping Dart on the floor, causing the departure of the original design team, kind of helped to Dart's success.

The political wars at Google with Dart are quite visible from outside, with Fuchsia picking up Flutter, and strangely the future of Android UI looks pretty much like Flutter, after too many times asking Android team about what was their opinion on Flutter for Android development at IO Fireside, meanwhile the developers' survey has had questions about how much we cared to see it supported on Kotlin multi-platform.

So yeah, had Chrome decided to push Chromium VM no matter what, Dart would be as successful as Go by now, after all younger generations don't seem to have any problem being Chrome developers.


Dart is an example of what happens to a language when corporate support is taken away. People lose confidence in the language.


Right. Programing languages by advertising companies have high adoption rate.


You're saying that as if it's not true

How many languages are there released by advertising companies?

Just to show the influence, python was an obscure programming language until Google started using it.


Actually no, Zope was quite famous during the first .com wave.

But Python has had many interesting sponsors throughout the years, not only Google.


A good example lies in Kotlin, as well.


Well, dev-oriented projects by Google and Facebook fair well...


I would think that would be a knock against it with the reputation of Google abandoning projects.


Java has genetics and it is many times more popular than Go. I'm not sure absolute adoption of Go is a good way of divining programmers opinions on genetics.


The popularity compared to what? How do the numbers stack up?


Oh, I'm not by any means saying it's the most popular language. I'm just comparing strictly based on the comment, people who like go vs people who will never use it because of its lack of generics.


>I wish they would just freeze the language and not add anything. I like it the way it is.

And a big share of users wishes they add generics - judging from it being the #1 voted feature in the annual Golang polls.

Not to mention the potential users that are put off because it doesn't have Generics...


Once they add generics, I will stop laughing at the language, but still probably won't use it. There's very little if anything it adds over C# or modern Java.


Until Docker or Kubernetes fad doesn't go away, having to deal with Go is something that those of us that rather use C# or modern Java have to face, so it will help if the language catches up with modern times.


But those large codebases will not be updated for some time. Or do you mean that at least new features could be written using generics?


The latter, as I always mention, platform languages always have the edge even if not as fancy as guest languages.

In the context of Docker and k8s, Go is the platform language so to speak, and although there are extension points for other languages, one has less integration headaches when using Go as well.


True. I think really a lot of people who are clamoring for generics in Go would already be working with more productive languages.

Generics is mainly for users who have committed to Go and new productive language features could possibly help them.


On the other hand, programmers don't always pick which languages they get to work with.

If I'm forced to use a language, it might as well have Generics than not...


At the moment it has something very valuable those languages don't have: A lack of Generics. Once they add Generics it will just be competing with those languages on the same turf.

It might not be for you, you may rely heavily on Generics in your daily work flow.

If I need generics in my work, I reach for Rust or C++. But when I want to write an easily maintainable microservice that's not trying to reinvent the wheel or need some clever datastructure to handle the work, I reach for Go, since that is what it's good at (at the moment).


How is having generics/templates to reinvent the wheel?

The one thing that put me off the most about using C for everything is lack of a common list/vector/map/set standard library for all types. Instead I reinvent the wheel in each project. Go cheats in this regard with compiler magic and that just pisses me off. Atleast you can in theory do printf in iso C.


How is being compiled the same turf as running in a VM?


I'm reminded of this Rob Pike quote from 2015 about what Go was trying to avoid:

"Java, JavaScript (ECMAScript), Typescript, C#, C++, Hack (PHP), and more [...] actively borrow features from one another. They are converging into a single huge language." [0]

[0] https://www.dotconferences.com/2015/11/rob-pike-simplicity-i...


I still find the most insightful Rob Pike statement (and the one that maybe induces a bit of forgiveness) that can give an idea for why Go is the way it is to be from this slightly older talk:

"The key point here is our programmers are Googlers, they're not researchers. They're typically fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They're not capable of understanding a brilliant language but we want to use them to be able to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt."

https://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Fr... at 20:33


Wow that's really condescending.


yes, but it isn't false


i mean... it's at least a bit surprising. the programming course at my uni (java) got to generics within the first year... i'm sure the hiring requirements at google are a bit higher than that?


and got people worrying about such generic things instead of the problem. It's not the fact that its hard or not, it's just yet another thing to keep in mind when you should be solving issues. Managing time is important, juniors no matter how smart, are juniors because they were not part of the industries before, they are getting the hang of having stuff in production and maintaining it, also managing time to ship, how much "generic" should the code be.

Go just makes you productive by removing lots of things to think about. I'm not saying that generics should or shouldn't be part of v1, I'm just saying that go lacking features to make juniors more productive is a feature


As opposed to us who only use features developed by Bell labs.


As it stand today, there is some elegance in its simplicity, but the lack of generics makes it unergonomic to write libraries. It's a good language to build applications, though.

This is less to do with the language and more about the standard library, but it has tons of cross-platform quirks that I feel aren't handled well. For example, Rust's standard library makes cross-platform work less footgun-filled, IMO.


I think the team is doing an excellent job with carefully and methodically evolving the language.


Has there been discussion on just creating a golang managed collections library that's generic and not adding general generics into the language?


Erik Naggum: "… if you think in terms of the imminent end of the world, _everything_ is soon food for the great garbage collector in the sky and whoever is not scrambling in panic looks like they aren't moving and have been passed by or are dying. … like, if you aren't using today's fad language in the very latest version of the IDE, you'll be left behind. aaaugh! but it's good that some people run like they are scared out of their wits. if they suddenly disappear over the edge of a cliff, a good number of people will notice in time and _not_ follow them."

Of course, this was part of an email thread around Common Lisp's popularity in 1999 (https://www.xach.com/naggum/articles/3141310154691952@naggum...) but I think it's more broadly applicable and still relevant two decades later.

Anyway, if you really want a "static" language target, perhaps push hard for official standardization (ANSI, ISO...). Standards encourage a lot of nice things, which admittedly are possible without standards, but less incentivized... For example, I can still write ANSI C as the gods intended, compile other ANSI C written decades ago, using a plethora of compilers across time (including the current year with the latest optimizations) so long as they claim to implement that standard and so long as the code is actually ANSI compliant. Such compilers might implement later standards too, or custom extensions -- but that's ok because it tends to be that I can easily make use of such code and such code can easily make use of mine à la carte! No jihad must be waged on all old code to update it under threat of being relegated to time-capsuled VMs.

But regardless, things will change, even if you have an island of stability from your standard. This isn't necessarily bad, because in order for there to be any improvement, there must be change. "Not every change is an improvement, but every improvement is necessarily a change."


With the little detail that ANSI C written decades ago most likely contain UB that a modern C compiler will gladly take advantage of, with all the nice consequences that it entails.


> I think we should start putting weight on stable unchanging software.

I think that they are just afraid of the income to stop coming in... so they keep working.


You can always stop upgrading and join the python2.7 crowd (apparently not as big as it appeared it would be a few years ago).


Python 3 upgrade was a complete disaster that took over a decade. They should have just called it a different language name and started at 1.0.

Edit: And, if Go doesn’t learn from Perl and Python’s mistakes it is going to suffer greatly.


I disagree, Python is now stronger than it was years ago. Now all companies that I interact with are magically on Python 3.

They were also estimating that it will take this long.

IMO they should give shorter time to upgrade, because everyone was waiting to absolute last minute to migrate.


Then hopefully the language will be forked and we can have go++, with generics, the ability to build cross platform gui apps and much more rejoicing.


> I wish they would just freeze the language and not add anything

> I think we should start putting weight on stable unchanging software

You would probably like CL then.


I think the go authors have had a reasonable balance of this when adding new features. Generics are quite useful.


I really like the Go standard libraries. I can do most of what I need with them. I worry some of the people calling for generics will move the language in the direction of massive abstract libraries. I don't want to include a Go version of Boost in everything I build. Complicated type signatures seem like an unnecessary additional burden for average programmers.

I really hope generics, like reflection, are only used when there isn't a simpler option. I honestly would have preferred and had more use for sum types.

I like the square brackets though. They look right for Go and it is more readable.


I haven't used Go but I'm curious, how do core data structures like hash maps work without generics? Does everyone just roll their own for their particular use-case?


> how do core data structures like hash maps work without generics

blessed implementations inside the language, slices, maps and channels are built in generics.

sync.Map is what the standard library version looks like. It loses type safety.

https://golang.org/pkg/sync/#Map


I'm looking forward to seeing these types of libraries improve with generics. It's notably more work to use these data structures, even if they are used rarely.


Go cheats with some built-in generic types. So you can declare a hashtable as a map of any comparable type to any other type. But yes you typically have to implement things yourself for more complex cases so that does limit the sorts of libraries that are available and the way you write programs.


Unfortunately "comparable" is not an interface, and the default implementation (which you can't opt out of) sometimes panics.


Like in everything Go, you opt out by using a clever hack like having a nameless non comparable field in the struct. Oh yeah.


The built-in types map, chan, array, and slice take type parameters, and they are usually sufficient for doing whatever you need to do.

It's incredibly great that, generally speaking, if I'm looking at Go code, the only kind of hashtable there can possibly be is the Go map data structure. The only kind of blocking queue there can possibly be is the Go chan data structure.

You will never see a LinkedTreeDeque or whatever other bizarre concoction someone might come up with. And people don't feel obligated to make every API an iterator of some kind.

Go makes being generics architecture astronautics impossible, and I really love that about it. Perhaps that makes me basic, but I am basic and happy.


> The built-in types map, chan, array, and slice take type parameters, and they are usually sufficient for doing whatever you need to do.

They are so sufficient you need to learn all these tricks by heart in order to do basic operations on slices:

https://github.com/golang/go/wiki/SliceTricks


A lot of software needs specialized data structures to perform their job.

They are not "bizarre concoctions".


Honest question; why use a comparatively exotic syntax for generics? Most other similar languages — Java, C# — and perhaps most notably C++ since its the closest analogue in terms of paradigm and domain, all use angle brackets (without getting into the semantic differences between "classic" generics and the STL).

AFAIK, Golang assigns no special syntactic meaning to angle brackets beyond comparison operators (correct me if I'm wrong though, I don't write much Go), and using a familiar syntax would make it easier to work with coming from other languages.


From the post:

> Angle brackets require unbounded parser look-ahead or type information in certain situations

So they want to avoid angle brackets so they can efficiently parse source code.


Thanks! I'll have to look into this some more but if anyone can volunteer the information, these questions come to mind:

- What situations could cause the look-ahead to be unbounded?

- How does the Go parser's implementation differ from those of the languages I'd previously listed which all also have angle brackets for comparison (and bit shifts, as another commenter pointed out) while apparently avoiding unbounded look-ahead?

- What challenges does the Go parser present when trying to adapt it to follow patterns more like those from the other languages' parsers?

- I'm assuming "unbounded" here doesn't mean "it could take unlimited time" but rather "it could incur non-negligible compile-time penalties;" do the benefits of a slightly-quicker compilation (which has nominally no impact on runtime performance) outweigh improved readability?


Unlimited lookahead parsers are not necessarily inefficient in terms of time. PEGs for instance run in linear time, but use up linear memory, which is the problem: https://en.wikipedia.org/wiki/Parsing_expression_grammar

> - How does the Go parser's implementation differ from those of the languages I'd previously listed which all also have angle brackets for comparison (and bit shifts, as another commenter pointed out) while apparently avoiding unbounded look-ahead?

I think parsing Java or C++ requires unlimited lookahead.



It not exotic at all, plenty of languages outside C++ family branch use [] for type parameters.

In fact, I think D is the only one using () as well.


D uses "()" for type declaration and "!()" for instantiation:

  template TCopy(T)
  {
      void copy(out T to, T from)
      {
          to = from;
      }
  }

  /* … */

  int i;
  TCopy!(int).copy(i, 3);
The parens can also be omitted in some cases.


It complicates parsing and creates ambiguity. It also makes it harder to create tooling.

> AFAIK, Golang assigns no special syntactic meaning to angle brackets beyond comparison operators

Go has also got bit-shift operators << and >>, which wouldn't interact well with angle-bracket notation.


>Also, Go has bit-shift operators << and >>, which wouldn't interact well with angle-bracket notation.

So do Java and C++. This is a solved problem in parsing. The overall point that angle brackets make parsing more complex stands, but bit-shift arguments are irrelevant.


With the little detail that their lexer makes use of type information, while Go one doesn't.


"Solved" is the wrong goal. It would be much better if the problem did not exist in the first place.


> Angle brackets require unbounded parser look-ahead or type information in certain situations

So.... they'd rather pull the "it's hard to do" or the NIH card, than make it easier for developers switching between languages? Interesting choice. Someone mentioned "condescending" -- that description fits perfectly.

And there I was thinking that COMPILER WRITING should be hard - as hard as possible - in order to make the code which is to be compiled as easy to write as possible.


I think they actually make a fair point because in this case "hard to do" probably equates to "makes the compiler a lot slower".

Go is very easy to switch to from most other languages so I don't think making it harder to switch is a design goal from the team.

When Go came on the scene, I actually really appreciated the fact that they truly explored what a new language could do differently, especially because it was coupled with a strong philosophy.

Now, since 1.0 there have been plenty of decisions made which I dislike. Still, I think the glasses through which you choose look at the Go teams motive aren't fair. Why wouldn't designers of a programming language like Go think it through very carefully, weigh every angle and decide to settle on a lesser used but possible equally valid solution compared to 80% of the languages out there?


> I think they actually make a fair point because in this case "hard to do" probably equates to "makes the compiler a lot slower".

They are wrong in this case.

When considering whether to allow `foo<T>();` in Rust, we measured the performance impact that infinite look-ahead / backtracking would have in that case. The result was negligible.

Why? Because the amount you have to look-ahead, before you can say "definitely wrong; let's turn back", in realistic code is bounded to maybe max 30 for some very complex generics. It's however much more likely that no back-tracking occurs at all because the parse will be correct.

When engineering your compiler, you can always make choices about which path is statistically more likely, as back-tracking in a well designed language is usually pathological. The theoretical O(..) complexity is largely irrelevant.

(Source: I was the main maintainer of rustc's parser and refactored large parts of it.)


If the type keyword needs to be added anyways, why not angle brackets then? Is it still ambiguous?


The way I read it, the type keyword would only be used in when declaring generic functions/types, but the angle brackets syntax has clashes when calling generic functions.


Just use guillamets already.


Link for those who are curious: https://en.wikipedia.org/wiki/Guillemet


‹‹››


I know it's unpopular but judicious use of significant white space would solve the ambiguity too.


Perl allows optional delims if ambigious. so if the best set <> is ambigious double or triple them. But much easier would be to demand uppercase T type variables.

   a, b = w < x, y > (z)

w is lowercase, unambigious. Parsed as list of comparisons.

  a, b = T < x, y > (z)
Ambigious, so use

  a, b = T <<< x, y >>> (z)
instead. These cases are very rare. Or demand parens for such ambigious lists of comparisons. Might be too late already.

Of just demand the type keyword there also:

  a, b = w < type x, y > (z)


If they finally end up adding any kind of generics support, it feels much more natural, from my experience with languages that use [] and () for type parameters, [] are much better visually.


This is a good move, which will make Go more consistent. Making custom generic and builtin generic consistent absolutely makes Go more easy to learn and read.


I liked the alternative proposed later in the thread:

    gen T   type pair struct { a, b T } // contrast with type pair(type T) ...
    gen T,U type W struct { a T; b U } // contrast with type W(type T, U) ...
    gen T   func Print(s []T) {...}  // print a slice of T
or using `forall`

    forall T, type pair struct { a, b T }
V readable IMO


> Angle brackets require unbounded parser look-ahead or type information in certain situations

I wonder how this is solved in Java, and C++, and C#, and...


It is solved by doing unbounded parser look-ahead (if you need that) or by requiring that all tools have full type information to understand programs (if you need that).

It is definitely better for tooling not to need either, both for human readers and mechanical tools

The example in the mail shows that using angle brackets with Go would require full type information, making simple tools like gofmt impossible.


Note that C#, Pascal don't "know" about known types during parsing like parsing C/C++ requires, it knows how a type is formatted, what it's looking for is: '<' ValidType (',' ValidType)+ '>'

If that's there, it's a generic, else it's an identifier, and somewhere up the parsing chain will take that up as LessThan.


> making simple tools like gofmt impossible.

So now we're making language design decisions based on the limitations of the bonus linter?

My opinion of Golang drops more and more with every new detail I learn about it...


One of the benefits of Go is super fast compilation time. Unlimited look ahead is likely to make the compiler slower. Ergo, it’s not a great idea.


Parser speed is negligible contributor to slowness in any compiler. rustc has a couple of places were it performs bounded lookahead to supply suggestions for incorrect code, but the grammar of the language is regular. 3rd party tools don't have to worry about it, and users get accurate suggestions. The cost is 1) you have to implement a more complex parser while 2) making people go "you already know what I meant, just take it without me using the 'ugly' turbofish". It think this is the correct approach for language design.


Go has a lot of problems, but continung to support gofmt's quest including the simplicity it desires isn't one of them.


You can see the trade-off made here in Rust. When parsing a type, Vec<i32> is no problem, but the constructor of that type (in an expression!) must be written Vec::<i32>::new().

This operator is affectionately called the "turbofish" and can often be avoided because of very good type inference.


And this is why the Turbofish exists in Rust.

https://github.com/rust-lang/rust/blob/master/src/test/ui/ba...

The key to parsing that is line 35. Is the line a tuple containing two booleans, the first the result of a less than, the second the result of a greater than, or is the line a templated function call, with two template arguments, "woe" and "is"?

(It is the former in Rust, and the latter is the apparently magical third option of

  oh::<woe, is>(me)
though of course "woe" and "is" would need to be types, not variables, in that case.)


No way. Really very informative, thank you! And I will stick with C++, thank you!


I believe the point they are making isn't that it's impossible. It's that with the way they have parsing now, the complexity of using angle brackets vs the complexity of the other options make the other options much more desirable. That seems both entirely reasonable, and language/parser dependent.


This article has good discussion of this problem:

https://blog.dyvil.org/syntax/2016/04/19/angle-bracket-gener...


Thanks! I was trying to figure out why angle brackets would be a problem and this article really explains it well (consider I know very little about any of this!).


Parser lookahead...

They even say that it is possible, but it makes producing useful error messages harder and makes the parser more complicated. they are not saying it is not possible, they are just saying it's not preferred to do.


In some languages unbounded parser lookahead is enough. But parser lookahead does not solve the ambiguous Go example given in the mail. Only type information would.


Why doesn't the same idea of adding a type keyword work there too?

a, b := w<type x,y>(z)


They solve it by using time consuming multi-pass compiling


parser look ahead makes the compiler complex and slower and that goes against the Go goals


C++ is famously Turing-complete to parse - not a desirable state of affairs.


I did not see digraphs mentioned. Could look like <: and :>.

The formatting tool could even normalize that to some prettier unicode.


Are they adding Java style generics (type erasure), or C++ style (compile time specialization)?


The go2 proposal (as currently implemented) is a source-to-source translator back to go1, so neither in that case.

As for the existing implementation of generic map[K]V, generic []T, chan(T), etc., it's a best-of-both-worlds mix - a kind of erasure (there is only one map implementation in a Go binary) but with a static vtable for accessors without Java's need for boxing - all possible owing to the clever coupling between the runtime and the compiler.

See https://dave.cheney.net/2018/05/29/how-the-go-runtime-implem...


As I understand it, the language spec is designed so that compile-time specialization is possible but not required. It could be some mixture of both.


Honestly, I prefer the parenthesis notation to the square or angled brackets. It is perhaps a bit verbose, but easy to read in my eyes. Not to mention the keyboard problems with non-English keyboard layouts.


Doesn't [ ] have similar problems? Suppose I write:

a[x](z)

Is that a read of array a with index x followed by a function invocation with the parameter z.

Where it could also be a type conversion of z into generic type a of x.


The issue isn't the interpretation; it's the parsing. It doesn't matter to the parser in this case if x is a type or an int. You'll have the same AST either way. But if you have f<a,b>(x), it matters if this is a generic or a pair of comparisons because the AST would be totally different.


Funny how we add 100 new emoji per year, and yet we can't seem to be able to add a new matching pair of characters in our keyboards for 5+ decades...


Such as ⸤ ⸥ 「 」 ⟦ ⟧〔 〕⟨ ⟩ « » ⟪⟫ ⦅⦆ ⦉⦊ ⦕⦖ ⧘⧙ ⦓⦔ ⁅⁆ ... ?


How many of those emoji are on your keyboard?


On my iOS virtual keyboard that would be all of them. Heck, the Mac laptop's touch strip also features a selection.

But that wasn't my point. It was that we get a ton of BS cosmetic/fun items on the Unicode standards, and we can't get a few simple glyph additions on our hardware keyboards that would seriously help programmers for decades to come...


seems like you could just not use ',' as the separator character in type declarations. +-*^% I think have the same problems, but @#$ are available. weird syntax, but go already makes the tradeoff, do what's fast to parse.


You have emoji on your keyboard?


This is much more readable IMO.


Whatever!! Go finally brought generics. The same thing which it used to criticize java for Lol


can someone just stick this thread forever on top of HN listing


If go gets generics I will never use it again.


Yeah, me too, the whole appeal of Go for me was that it was as barebones as C (with GC and concurrency). It was a breath of fresh air. Generics opens the door to the abstraction olympics in other "modern" languages. Might as well just go back to Java.


When go gets generics a lot more businesses and developers will start using it.


Why?


I wondered this too. It's not like there's a part of a language you MUST use. Perhaps they are fearful that it'll grow and grow and add features in that will make it difficult to learn and unwieldy. Stroustrup always said that new languages seem fast and easy to learn precisely because they are new languages and don't have the features of maturity. Perhaps this is the case here.


He is quite right, yes C++ is a monster dragon, but most languages of similar age only look simple on the surface, even a beginners friendly language like Python.

Beneath that simple surface for beginners lies a multi-paradigm language, with overloading, metaclasses, dynamic code generation, multiple inheritance, breaking changes across minor versions in 30 years of history, a standard library that can be used as doorstep when printed, several implementations not 100% semantic compatible with CPython,.....


Yes, it's good isn't it!


Maybe because you take away one of the big advantages of Go which is easily maintainable code, and end up with just another clone of Java/C#, so why don't you just use those instead?


Generics are simple to understand, please explain or show an example of unreadable generics that wouldn't be unreadable without them.

But yeah to me Go is pointless and you should better be with C# or Kotlin


The type variable in any generic declaration is inherently unreadable. What's <T>? Every language with generics has tried to come up with ways of making this less opaque. Typeclasses, concepts, traits, interfaces, bounded type parameters. If you implement one of those then you'll have another unforeseen problem on your hands, playing wack-a-mole until you have C++.

How about just code gen your generic implementations then check them in. That way I can see what's going on without having to guess. The whole thing is about saving time typing and DRY right?


The type variable in any generic declaration is inherently unreadable. The concrete type variable of a generic parameter does not matter at all, you need not to clutter your brain thinking over it.

With a simple T you do not know anything about the type and you cannot do anything else with it directly except using the root type methods of your type system (e.g get hashcode, toString, etc)

Most generics to be useful needs either: 1) To be type tested (e.g through reflection). This allow you to manipulate it in a fine grained manner and you can know exactly what it's type is. But generally we want 2) to abstract over many types in the same way because those type would have a same invariant, a same behavior. Some language allows you to represent this through union types instead but there's nothing wrong to say that T extend an interface/concrete class that specify what will be accessed from T inside the function. There is no cognitive overhead, no ambiguity. What would have been many types become simpler, factorised under the same contract, the same interface.

If you implement one of those then you'll have another unforeseen problem on your hands, playing wack-a-mole until you have C++. This is a claim, could you explain it? I see no reason to think that way.

C++ "generics" are cancer, we can agree on that.

How about just code gen your generic implementations then check them in. I'm not sure to understand. Would that be like C++ template? What's the difference?

You would like the N redundant implementations of a generic function to be visible? Why desire this clutter? And the alternative, manually maintaining redundant code is error prone and a maintenance burden. Also the fact that there is an invariant, a meaningful intersection of behavior between those types become hidden instead of being explicit through an interface/type test.

what's going on without having to guess. there is zero guess involved as explained above, it's all type safe and your IDE will autocomplete only the shared behavior.


How common is the actual confusion regarding less or grater than and templates? Never bothered me.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: