8 ms·
Nice write-up! At my personal level, I feel nothing about Iterators or even Generic. I can live with or without it, and kind of dont mind it to be used by libra
by adeptima 2y ago
Nice write-up! At my personal level, I feel nothing about Iterators or even Generic. I can live with or without it, and kind of dont mind it to be used by library authors.
I didnt had a single line of code broken by golang version up updates in 7+ years, scanning through golang source code is always a pleasure. No hidden magic. I dont read documention either - just surfing inside of source code by clicking with CMD key.
My main KPI for Golang is the ammount of clicks required to understand internals ... very few compare to other languages.
If its stamped by guys like Russ Cox (rsc), I can sleep well too.
- 38 2y ago> No hidden magic thats the whole point of the article. this change trashes that. now many loops are going to have hidden magic
- adeptima 2y agoI guess my system got immuned to such things after TS/JS coding, but if 20% of community will say it has "hidden magic" I'm not excited too. Fast learning curve for new hires is a top golang feature for me too.
- unscaled 2y agoGo always had hidden magic: - Lowercase symbols are private to the package they are declared at. - A function called "init" will get executed implicitly on startup. - You can have multiple functions called "init" in the same package or even in the same file. - Files ending with "_unix.go", "_linux.go", "_windows.go" etc. will only be compiled when compiling for the specified platform. The exact list of platform is very hard to find in documentation. - There are a handful of magical built-in function that have lowercase names. - Some built-ins were generic long before generics were introduced to the language. - The copy function is defined as "copy(dst, src []Type) int" (i.e. both src and dst have to be slices of the same type), but "As a special case, it also will copy bytes from a string to a slice of bytes". There are many cases of magical behavior in classic, pre-Generic Go. Sure, if you read the documentation you can learn about these thing and you wouldn't be surprised (although good luck figuring out the order of calling init() or finding out what happened when Go introduces a new compilation target platform that happens to have the same name as the ending of one of your source files). The thing is, if you read the documentation about iterators and see that your iterating over the results of a function that returns a another function (rather than a slice, string, map or channel), you also wouldn't be surprised. And unlike the old magic, the new magic is always transparent. You can always tell what an iterator function by looking at its source code. But you can't exactly tell what suffixes trigger platform-specific compilation without looking at the Go compiler source code, and knowing where to look.
- foobiekr 2y ago"Lowercase symbols are private to the package they are declared at" This isn't magic, it's just a clever convention.
- kortex 2y agoA sufficiently clever convention is indistinguishable from magic.
- onefiveone 2y agoexcept there's no smoke and mirrors for this character saving trick
- lifthrasiir 2y agoIt is a part of the language rules that you can't ever change if you don't want it. It is magic in that sense.
- mariusor 2y agoI always thought that lack of "magic" in a programming language means that when (as a human) you read through source code you are able to reach the end of the program. Opposite to that, in a language that has "magic" you reach a point where you don't know where execution will go next without the help of the compiler (or a heavy duty IDE that translates for you).
- lifthrasiir 2y agoThat's very subjective I guess, because it would also depend on your familiarity with the subject matter. I can for example easily read and understand a recursive descent parser in any language because I have implemented it multiple times and can catch a common pattern. Unless the language in question corrupts that pattern (highly unlikely unless it's an esolang :-), that definition of "magic" should be largely independent from the language itself.
- TheDong 2y agoIf iterators are hidden magic, how are the following not hidden magic: for i, v := range someSlice { ... Shouldn't that be eschewed as magic, and instead we should write: for i := 0; i < len(someSlice); i++ { v := someSlice[i]; ... They both de-sugar to the same thing (well, now they do, it used to re-use the same 'v' in the first one, so it used to be subtly different, but they changed the language's hidden magic). How is the channel loop not hidden magic? for v := range channel // magic for for { v, ok := <-channel if !ok { break } } The iterator proposal is adding some sugar which is _less hidden_ than the current 'for range' loops, and people are complaining that's magic?
- 38 2y ago> for i, v := range someSlice { ... what a ridiculous comment - every single programming language has this or similar syntax for iterating a slice.
- TheDong 2y agoAll the languages I can think of that have iteration over a slice also have the ability for users to define iteration over custom collections, such as with generators or whatever... yet the comment I'm replying to is saying custom iterators, something every language has, is too much magic, so clearly "every language has it" isn't enough justification for something not to be magic for them. Anyway, not every language has it. C has arrays, but doesn't have any iteration sugar for them, and the general attitude of gophers does usually seem to be "if C didn't have it, it's not simple, it's magic", and that Go should just be C but with a GC, goroutines, and builtin hashmaps.
- evantbyrne 2y agoHaven't developed an opinion about iterators yet but generics are a godsend for writing libraries. The first time I attempted to create a database toolkit for Golang I quickly abandoned it because of limitations with the type system. My first attempt post-generics, REM, went much more smoothly. Been enthusiastically working on a follow-up privately. I honestly don't think I would be writing much Golang without generic types.
- aatd86 2y agoAt first, even if I knew they were useful, I didn't have much use for generics. But it came increasingly handy and there is even code that I could not have written without these. Will probably be the same for iterators.
- jkrejcha 2y ago> Will probably be the same for iterators. I think especially because people were already doing iterators, just in a not-really-specified way, as the discussion[1] for this change mentions. (I mean people were kinda doing generics too with code generation but that was probably less doable for library code...) [1]: https://github.com/golang/go/discussions/56413 https://github.com/golang/go/discussions/56413
- jimbokun 2y agoYeah, a Cassandra library has an “iterator” that reads a row’s data into a struct pointer, and returns false if there’s no more data.
- phplovesong 2y agoGo has very much "magic" all around. Take a look at goroutines, they are pure magic. Theres also lots of implicit magic going on with magic comments, file names convention etc.
- lifthrasiir 2y agoWhile I agree that Go has lots of magics, probably far more than the average programming language, it seems that Go has also successfully hidden many if not most magics so far.
- anal_reactor 2y agoI worked in a company that used golang but my position did not and that was pain because golang's syntax is "we do things differently because we can" so whenever I needed to make a small change in existing code, it always turned into a bigger project because I never understood what the fuck was going on in that program.
- lifthrasiir 2y agoYeah, that's a curse of knowledge to be frank because you can see many magics once you have used many other languages and it is generally a good instinct to be skeptical about those magics anyway (Go included).
- ithkuil 2y agoI agree about directives embedded in comments. Especially things like // go:embed But goroutines? They are a foundational language feature with clear syntactic demarcation and documented behaviour. I think that in computer science "Magic" doesn't mean that the implementation is hard to understand. Magic means that the behavior is surprising, that there is misdirection involved etc
- saghm 2y agoMy hot take is that "magic" is just a pejorative term to dismiss any abstraction that someone doesn't like. It's subjective, and IMO it's used mostly as a thought-terminating cliche rather than providing any value to a discussion. Sometimes it seems like people throw around the word "magic" like it's some morally dubious shortcut used by programmers who lack the discipline to resist its temptations. I'd argue that making a good language that doesn't require using "magic" is actually _hard_; it needs to differentiate from existing languages enough not to be redundant but still try to fit into the non-uniform expectations of users. Rather than saying that a language "has magic" or "doesn't have magic", I wish it was more common for people to directly state that a language works like they'd expect or point out the areas where it doesn't (which can be separated from a value judgment of whether something is "good" or not). If anything, I think that saying a language works like you expect is _more_ of a compliment than saying "it doesn't have magic" because it properly conveys the sense that our expectations are fairly narrow in comparison to the entire design space and require skill to identify rather than something obvious that people would only avoid by choice.
- tapirl 2y ago> ... No hidden magic ... This has been changed since Go 1.22. Go 1.22 introduced magical hidden code: https://go101.org/blog/2024-03-01-for-loop-semantic-changes-in-go-1.22.html https://go101.org/blog/2024-03-01-for-loop-semantic-changes-...
- ithkuil 2y agoIs it magic? The reason they changed the behaviour is because the previous behaviour was surprising and thus "magical". The new behaviour is more consistent with what you think about what is a scope of a variable. The fact that a compiler has to add some code to instantiate a variable is not magical. Otherwise all what compilers do would be magical
- tapirl 2y agoI never doubt it is a good change for "for-range" loops. The change for "for-range" loops didn't introduce magic hidden code. But the change on "for;;" loops creates more surprises than before and gets rare and tiny benefit. It introduced magic hidden code. Please read that article for what is the magic hidden code and the surprising cases.
- ithkuil 2y agoyeah I see; that said if for;; behaved differently than for range it would cause a different set of surprises, so I guess consistency was deemed more important.
- tapirl 2y agoThe cost of making the consistency is too large and the benefit is too tiny.
- ithkuil 2y agoThe surprise factor is only for the current generation of people who are used to it and who are used to other languages that the same kind of for loop and closures that can escape (basically only JS?) But the internal consistency between the for;; and for range allows you never doubt about the rule again once you first learned it. Yes, there is the risk that you'll get it wrong once (if you first learn the language or if you are used to the old rules) but if the language authors had only fixed for range, then a lot more people would get for;; wrong just because they would be never sure which way it would be. So the only "solution" would be to never fix "for range" or disallow for :=;; ? In any case I think that if you really care about the old semantics, it's not a bad idea to making it obvious to the reader that you intend to directly or indirectly take a reference to the iteration variable and that it effectively survives the loop body with: var i int for i = 0; i < 4; i++ {