20 ms·
The best summary I read recently is that go isn't a bad language, nor is it a particularly good one. What fascinates me is the way the Golang community have con
by grabcocque 10y ago
The best summary I read recently is that go isn't a bad language, nor is it a particularly good one. What fascinates me is the way the Golang community have concretised that essential middle-of-the-roadness as the language's prime virtue. That, of course, has long been Java's prime virtue as well. (see Blub Paradox)
By putting "we're okay with being okay" as your Big Thing you're clearly pitching for that vast bulk of mid-quality developers that make up the huge middle chunk of corporate devs, the space where Java reigns supreme.
- rpercy 10y agoDo you have an example of the community celebrating mediocrity? My impression is of a community willing to go without some features, in order to preserve those it values. Namely simplicity, explicitness, terseness, and consistency.
- MichaelGG 10y agoExplicitness and terseness seem a bit at odds - I wouldn't call go code very terse at all. It seems verbose and repetitive. Consistency? Aren't only some built in types blessed with generic functions? Mediocrity? The preference for writing loops over simple maps or folds is a bit mediocre. IIRC in Tim Sweeny's "Next Mainstream Programming Language"[1], he notes that around 90% of all the loops in Unreal are folds or maps. Maps and folds are just simpler than loops, without even appealing to terseness and elegance. Hey I know I'm in no place to judge -- the creators of go and Google overall have accomplished more than I'll ever do. I just really cannot grasp the mindset and penchant for unexpressive languages. 1: http://lambda-the-ultimate.org/node/1277 http://lambda-the-ultimate.org/node/1277
- sidlls 10y agoMaps and folds are implicit loops. For some explicit is simpler.
- mattnewton 10y agoNo, maps are conversions between types containing other types. Maps are much more powerful than just doing something over an array in languages that support a functional style.
- sidlls 10y agoThe original comment was comparing maps and folds to loops, not the general application of maps.
- Scriptor 10y agoMaps are explicit transformations of data. For some, making the business logic explicit is simpler.
- solidsnack9000 10y agoLoops are just implicit goto... The argument for maps and folds is the same as the argument for structured programming in general: using common/reusable idioms brings clarity and familiarity.
- sidlls 10y agoTerseness doesn't necessarily bring clarity.
- solidsnack9000 10y agoIt's the recognizability, not the terseness, that brings clarity. Although Python's approach is not terse -- `fstyle = [f(x) for x in arr]` -- it is eminently recognizable. Your argument is not really about anything I specifically said; and without something to counterbalance, it argues against structured programming, too.
- sidlls 10y agoHow does it argue against structured programming? My argument is that "recognizability" is in the eye of the beholder. One programmer's "map is a powerful abstraction over transforms, for example loops" is another's "this is some cutesy code/math creole by a CS graduate who desperately wants to find nails to apply his functional programming and applied math hammer on". That's a fairly harsh way of saying that at some point the abstraction isn't clarifying, whether it's recognizable or not. Disclaimer: I'm a big fan of functional idioms (they're one of my favorite parts of Rust, for example). I'm not so much a big fan of absolutism or over-generalization.
- skybrian 10y agoThe preference for maps and folds looks like a fad to me. I can use them but I don't think it makes the code any easier to understand, just different.
- Groxx 10y agoI dunno, ruby has some nice tendencies here, like `out = [1,2,3].map(&:to_s)` which is small and descriptive[1]. Compare that to: out = [] [1,2,3].each do |x| out.append(x.to_s) end IMO that's not fad material - that's progress. Maps and folds can totally be abused to produce inscrutable nonsense, but for small, common operations they're often much more obviously-correct. [1]: `&:method_name` is extremely-common shorthand for "call this method"
- XorNot 10y agoI had no idea what you were trying to do in the first paragraph whereas without knowing much ruby I can easily read the intent of the second.
- sheepmullet 10y agoThat has more to do with familiarity than anything else. A tale of two cities is an easier book for an English speaker than Les Aventures de Tintin. Map applies a function to each item in a collection. As pseudo-code: Collection.map(function) And in the parents example we have: [1,2,3].map(&:to_s) The only Ruby specific part is &:.
- Cthulhu_ 10y agoIt does though. Maps and folds - and functional programming in general - focuses on the /what/. For-loops on the other hand tell the compiler / cpu the /how/. Summing is a nice example. A naive for-loop will just iterate through the list, keep a variable around, add the next item in the list to it. In functional programming (or with a reduce), you tell it to sum in a more concise way - but more importantly, you don't tell the compiler how exactly it should do it. It's trivial with functional programming to make the task (for example) multithreaded or to use advanced underlying cpu tricks, without you as a developer needing to know how exactly it does what you ask it to.
- spion 10y agoThats not a strength of Go. Structural interfaces, channels and performant M:N green threads are its main strengths, and AFAIK there is no other language that provides a similar combination in a familiar C/ALGOL-like packaging. If such a language existed and had generics and Swift or Rust style error handling as well as some backing by a large-ish corporation / organization, I think that language would be preferred to Go. More expresiveness isn't always better. Examples that hit the sweet spot are C# / Swift (C# really needs algebraic data types). Beyond a certain point, you will start to lose users. Haskell is very expressive, but few will ever have the time or patience to learn enough to build their perfect monad transformer stack and take advantage of the mtl typeclasses to easily use it. Even though it does have M:N green threads, channels, STM and everything. In fact, Haskell could probably compensate for this and beat Go by having excellent library documentation and well written, focused tutorials for the working engineer.
- reikonomusha 10y agoI feel like maybe 10 years ago no one would utter something like "C# needs ADTs" because they didn't have mainstream appeal, despite computer scientists' understanding of them.
- spion 10y agoYes, things are moving forward, even if slowly :)
- tu7001 10y agoI don't know go, can't you write a map in it?
- mattnewton 10y agoNot a type safe one that works on your own types.
- s_ngularity 10y agoYou can't define a polymorphic function map, but you definitely could definitely define a map method for your own monomorphic container type.
- watwut 10y agoThe loop and map are equally readable, it is just that some people are used to one form more then the other. More importantly, how many character needs to be used for simple idiom like that has zero influence on how maintainable your system is going to be few months later on, how fast it is and so on. The difference between loop and map wont make you do less or more bugs. It may make you read the code few seconds longer first time you encounter form you are less used to - but then you will adjust and read it just fine.
- solidsnack9000 10y agoIt is not necessarily easy to recognize when a loop is a map or filter -- I think that's the issue. It's why someone like McSweeney would bring it up. The Python approach -- where maps and loops share a lot of syntax -- is maybe the middle way. On the one hand, it's not an approach that gives rise to `.map()`, `.collect()`, `.flat_map()` and so forth; on the other, it's marked out as something returning a result.
- lewisl9029 10y agoFunctions are trivially composable, while imperative loops are not. The difference that makes in terms of maintainability and readability of non-trivial applications is hard to overstate. Writing code in terms of small, composable, reusable functions with a clear single intent (through good naming), that you can then mix, match, and reuse to compose into larger functions is what makes good functional code so much easier to write, test, and reason about than imperative code. My favorite intro to functional programming concepts for those used to imperative coding is Sott Sauyet's Functional Programming presentation: http://scott.sauyet.com/Javascript/Talk/FunctionalProgramming/ http://scott.sauyet.com/Javascript/Talk/FunctionalProgrammin... The presentation makes heavy use of JavaScript and the RamdaJS library in its examples, but the concepts are universally applicable to any language with the necessary functional programming primitives. It also does a great job of comparing imperative and OO implementations of a solution to a problem vs the functional implementation. I highly recommend taking a look if you're even slightly interested in why so many people are starting join the functional programming bandwagon. So what I'm trying to say is, it's not just a matter of readability. Although if anyone still wants to argue that imperative looping is anywhere close in readability compared to functional composition for non-trivial cases (think multi-level nested loops vs composing multiple functions), then we should just agree to disagree since I don't foresee that becoming a productive discussion.
- artursapek 10y agoWhat on earth is a "good" language? > you're clearly pitching for that vast bulk of mid-quality developers that make up the huge middle chunk of corporate devs That was actually something Google aimed for with Go, and I don't see what is shameful about it. It's a simple language on purpose. It is meant to be easily learned by any developer, and similarly Go code is meant to be easily read. Also, what sets Go apart for me, in addition to this simplicity, is the tooling and documentation. I think people mistakenly yearn for languages that are exciting to use or offer interesting abstractions. This stuff is fun for the individual developer but costs an organization in the long run. Go is bland on purpose. Notice how between versions most of the headline updates are internal improvements (GC, tooling, general performance)
- aeturnum 10y agoWhen I think about Go in comparison to other languages, I think of car metaphors. Lots of people talk about cars that are good. Some people think a good car is fast, some people think a good car is low maintenance, some people think a good car is eye-catching. They are all right, those are all descriptors of good cars. Go, however, is like a Toyota Corolla or a Honda Civic. It's dependable, but relatively plain. It's not necessarily a joy to drive but there's not much of a learning curve. It lets you go fast, but not so fast you'd hurt yourself. It's designed with safety in mind, so much so that it can feel a little over-bearing at times. It's not a language that draws you in with one clear feature or philosophy. I've used it very successfully and I still find myself rolling my eyes at "go-isms." Lines of "ok, err = ...", rewriting extremely similar data structures, careful channel management, etc. In a list of dependencies, the go dependency will need the least maintenance time and tuning, but what you do need will often be drudgery. Go is a useful language, but it's a language that has purposefully stripped out all the magic. People like magic, they miss it.
- artursapek 10y ago> Go is a useful language, but it's a language that has purposefully stripped out all the magic. People like magic, they miss it. I agree with everything you wrote except this. After 3 years in a job where I had to use Ruby on Rails, I am utterly tired of "magic" and I regret the many hours of my life I have wasted debugging issues that were created/concealed by it. Lack of magic is a feature in my opinion. But as you said, that's all this is - opinions.
- user5994461 10y agoJava reigns supreme because there is nothing which come close to its characteristics in terms of capabilities, libraries supports, tooling, performances, easiness to learn, simplicity and maturity. If you want faster or lower level, you gotta move to C++, which is uber-hardcore in terms of non-simplicity and impossible-to-learn. If you want easier, you gotta move to python/ruby/node.js, which are a joke in terms of performance and concurrency, with the last 2 being fairly young and immature (< 10 years). Either way, the tooling sucks compared to Java, if not entirely non existent. Entreprisey development is on Java because that's what best for them. Web development is on something else because they pick what's cool and trendy.
- tyre 10y agoRuby came out in 1995, 22 years ago. It is neither young nor immature.
- user5994461 10y agoOf course I mean ruby on rails when I say ruby. Initial release 2005. i.e. Young.
- closeparen 10y agoAre you using Struts or something? How could a 12-year-old framework not be old enough for you?
- deleted 10y ago[deleted]
- jankiel 10y agoRuby on Rails is a web framework, not a language. Also web dev is about shipping a product fast, that's why you don't see Java there.
- closeparen 10y ago
- sidlls 10y ago"Good" and "bad" aren't really useful descriptors without additional context. And what do you mean by "mid-quality" developers? That seems gratuitously insulting.
- dilap 10y agoNah. I like Go because the language itself is minimal yet powerful, and because the quality of engineering is extremely high. I am so tired of having to deal with bullshit because of poorly-thought-out and poorly-engineered tools; Go minimizes that. An excellent example is the handling of this bug report(§): https://github.com/golang/go/issues/12914 https://github.com/golang/go/issues/12914 which resulted in this language-change proposal: https://github.com/golang/proposal/blob/master/design/12914-monotonic.md https://github.com/golang/proposal/blob/master/design/12914-... And then these commits: https://go-review.googlesource.com/#/c/36255/ https://go-review.googlesource.com/#/c/36255/ I feel like any other language I've used would've just added a "monotonicTime" function and called it a day; the Go solution is impressive, elegant, and shows an exceedingly high level of care for the end-outcome results for the users of the language. To me, that's what makes Go special. (§After a rocky start; it took the core devs a bit to realize it was a real issue because within Google's special environment it isn't.)
- Groxx 10y agoI dunno... in some ways, the problem is that they didn't think it through to begin with, and chose something widely-known-to-be-ambiguous-and-problematic like "time.Now()", instead of choosing unambiguous names / structures from the start. It's kinda the equivalent of making a new language (nowadays) and not defining what encoding your native strings use. Of course it's going to cause problems. Except the timer issue has been around much longer than the standardization on utf-8.
- dilap 10y agoFair point! And I certainly don't claim that the Go devs don't make mistakes. They started with the theory that the problem should solved as Google does, by arranging that clocks don't run backwards. When it become clear that wasn't reasonable, they moved towards a new solution in a way that I felt was impressive.
- Groxx 10y agoIt's mostly-impressively backwards compatible, I'll definitely agree there. It's clever, and in many cases it'll do the right thing automatically. Since it seems that's their goal, they achieved it quite elegantly, and that's a tricky thing to do. (edit: and quite quickly! seriously, this is an example of a healthy community at its best) But personally I don't agree with the decision - it adds surprises when you try to convert times to other types and then compare things. Or convert to something else and then back to a time instance. I've watched things like this become the source of bugs many, many times - this will only make that worse, since now a "time" is two values but you can really only access one of them (the one that's equivalent to wall-clock, which is causing the problems). And they're particularly painful bugs, because the cause lies in implicit conversions and behavior. That seems to run counter to the "minimal surprises" that Go seems to prioritize.
- throw2016 10y agoI think simplicity is often the most difficult to achieve and requires deep technical expertise to deliver. It shows the creators have thought about the end user and usage scenarios. It would be a mistake to confuse complexity with quality or vice versa.