11 ms·
Replacing Clever Code with Unremarkable Code in Go
- xaprb 13y agoI didn't put much code into the article, but ask me if you'd like more details on exactly what I'm talking about -- in terms of real code.
- wooster 13y agoThe climber in the gif, BTW, is Jyoti Raju: http://en.wikipedia.org/wiki/Jyoti_Raju http://en.wikipedia.org/wiki/Jyoti_Raju http://www.youtube.com/watch?v=BPN3gLVDsOY http://www.youtube.com/watch?v=BPN3gLVDsOY
- SeanDav 13y agoCompletely OT: Is that climber clip genuine, if so is there a better source? Edit: Answered by wooster, thanks.
- DanBC 13y agoHere's a video from a different day (http://www.myspace.com/video/gnomeslice/amazing-wall-climber/49956326 http://www.myspace.com/video/gnomeslice/amazing-wall-climber...) I got that through TinEye, and then through comments left on various places. I think with a bit more noodling I would have got a name, but HN user Wooster got there 15 minutes ago. This is the kind of thing that can be hard to get an answer to using web search engines. Perhaps the Google search a day could be expanded to include "tricky" and "hard" levels?
- JulianMorrison 13y agoLike this, I presume: go func(){ for { select { case <-time.After(time.Second): log.Println("timeout") case <-stop: return case val, channelOpen := <-inputs: if !channelOpen { return } outputs <- process(val) } } }()
- xaprb 13y agoThat's a good example, yes.
- itsmonktastic 13y agoNice. I still haven't given Go much time, but I really like this form, where you can switch on multiple blocking calls. I've definitely wanted this in other languages where I'm using thread safe queues for communication, and had to do manual multiplexing into a new queue whenever I wanted to do a blocking get on multiple queues. Does anyone know of a convenient way to do this when handling multiple instances of python's Queue or similar with Haskell's Chan?
- njs12345 13y agoLooks like you can use STM in Haskell: http://stackoverflow.com/questions/5879128/a-way-to-form-a-select-on-mvars-without-polling http://stackoverflow.com/questions/5879128/a-way-to-form-a-s...
- itsmonktastic 13y agoThanks for posting this. I found something similar but on first blush didn't think it was quite right as I was mistakenly thinking that you could only do this for TChans with the same type. Looks like it might be just what I'm after! When I think about it, STM seems like it makes sense here, since you probably want the ability to cancel/rollback the blocking gets that didn't return. EDIT: Actually, this isn't right. The example linked does "if get from channel 1 fails, get from channel 2". I'm looking for "select" on multiple channels, where the result is based on the first channel to return. EDIT again: Apparently I can't read, and this does achieve what I'm looking for, I just have no basic experience with STM. Awesome, will try this later!
- masklinn 13y agonjs12345 answered for Haskell, I don't remember seeing a way to do this in Python though depending on the situation you could just use a single queue for everything of course. FWIW there's no primitive letting you wait on multiple conditions in threading, and Queue is implemented in terms of a pair of conditions.
- rustc 13y agoA little off-topic, but could you give some (Perl) code examples of this: > You feel initiated into an inner circle. You feel like you’ve discovered LISP in an alternate dimension (but you haven’t).
- xaprb 13y agoIt's tough to give examples of this in Perl without a lot of narrative (and sometimes a lot of code), but the technique I'm referring to is currying: programs that write programs, via functions that write functions. This, of course, is what you do all the time in LISP. It takes half the (Higher-Order Perl) book to illustrate the technique and its power. Which is kind of the point: shouldn't it be a commonplace thing that doesn't take so much work to get around to explaining and using?
- TikiTDO 13y ago> shouldn't it be a commonplace thing that doesn't take so much work to get around to explaining and using? Why? It's a reality of the world that more complex things take more time and more effort to learn. However, often that is because these more complex things allow you to do a lot of very useful things much more efficiently. I would prefer to drive over a bridge built by an engineer who learned all those difficult equations, material properties, and buildings codes as opposed to a high school kid with a few physics courses under his belt. Programming is similar in some effects. As you get better and better you acquire more and more tools to do what needs to be done. Now granted, if you are working on an interface that needs to be easily accessible to the widest range of people it makes sense to simplify. However, cleverness has it's place in code that is expected to be read by specialists. In the end, even if you avoid all the clever tricks and shortcuts you know, a large enough project will still be utterly inaccessible to a novice. The real challenge of projects that complex becomes less about the specific detail of how a piece works, but more about how all the pieces work together. If you're skilled enough to follow the design of a project like that, I don't think it's too much to ask that you either know these "clever" techniques, or you should be willing to learn. Looking at your code you linked in the article, I think part of the problem is the fact that there are entire pages of code without a single inline comment. When you're doing these clever things you really need to document every logical step in order to understand and verify your through process later on. You also have to be ready to accept that sometimes you will mess up in your cleverness. In fact, If you are getting a lot edge cases that's a good signal to go back, re-read your comments/design notes, and find where you could improve your approach. Ironically, I would argue that go channels are actually an example of doing something "clever" the correct way. These channels are very effective at separating a single concept from a whole pile of abstractions, and doing a lot of clever interactions beneath the hood in order to ensure it's all effectively synchronized. In other words, using go channels is using the same type of "clever" techniques once they've been abstracted away.
- ble 13y agotell 'em about package "robustly"!
- deleted 13y ago[deleted]
- peterwaller 13y agoI think this is one of the really great things about Go. Some detractors ask "There is so much to be gained by having generics! What would be lost if Go had generics? Nothing! Ergo, Go is wrong to not have generics". This line of argument is flawed. Go curbs the ability of people to write crazy (and ultimately mentally expensive) abstractions. The lack of generics in Go is very a good thing. Especially when it comes to collaborating on a large unfamiliar code base. I have been productive in Go and haven't missed the ability to write generic code so far. Usually it turns out there is another way to achieve what you want without them. If there isn't, maybe I'm trying to solve the wrong problem, or it is the wrong language for the task.
- MichaelGG 13y agoReally? I thought the reason Go didn't have generics is because they couldn't decide on an implementation that met their goals? That is, was quick and didn't emit a ton of code.
- peterwaller 13y agoI don't claim that was their goal. I think it's just a nice side-effect.
- aodin 13y agoRuss Cox, one of programmers working on Go, described the dilemma as: "do you want slow programmers, slow compilers and bloated binaries, or slow execution times?" He expanded on this dilemma with examples from major languages: http://research.swtch.com/generic http://research.swtch.com/generic
- masklinn 13y ago> He expanded on this dilemma with examples from major languages: http://research.swtch.com/generic http://research.swtch.com/generic My god, this is such completely dishonest bullshit strawman I'm impressed he had the balls to post that garbage. Java's boxing does not come from its generics, it's the other way around (java's non-Array collections have never been able to hold unboxed values), and C++'s template are pretty much unique in their complexity (and definitely not what PL people think about when talking about generics) and compounded by all the rest of C++'s baggage (D has C++-style templates and is nowhere as slow to compile). And his reaction to comments (that is, his complete failure to acknowledge how huge a strawman his original post is, and complete absence of response to any mention of C#, Eiffel, Ada, Haskell, MLs and others)... that is supposed to be a defense of goteam's thought process?
- tharshan09 13y agoI just kept staring at that GIF ...
- pmelendez 13y agoMe too... it is actually distracting if you want to really read carefully the article.
- k3n 13y agoI've seen it many times before, and it's always been amusing, but looking at it within the context of "clever code" is brilliant. That's exactly what it looks like some people have done (figuratively) to produce the code that they did.
- jlgreco 13y agohttp://en.wikipedia.org/wiki/Jyoti_Raju http://en.wikipedia.org/wiki/Jyoti_Raju
- realrocker 13y agoI wanted to say this but couldn't find the right words. The author manages to do it. This is something I wrote: https://github.com/adnaan/hamster https://github.com/adnaan/hamster. The whole experience of programming in Go is like moving from point A to point B in a straight line.
- jweese 13y ago> The channel is the analog to the Unix shell’s | character. This sentence was italicized, and rightfully so. I've written a few small Go programs, but I haven't run into a problem where I thought, "A channel is definitely the right solution here." Yet I love and feel quite comfortable with shuffling data through big shell pipelines. Perhaps I'll think of a channel next time I'm reaching for a pipeline.
- mratzloff 13y agoI find that I use channels mostly when working with goroutines. It's also a convenient mechanism for connection pooling.
- gypsobelum 13y agohttp://www.paulgraham.com/avg.html http://www.paulgraham.com/avg.html Programmers get very attached to their favorite languages, and I don't want to hurt anyone's feelings, so to explain this point I'm going to use a hypothetical language called Blub. Blub falls right in the middle of the abstractness continuum. It is not the most powerful language, but it is more powerful than Cobol or machine language. And in fact, our hypothetical Blub programmer wouldn't use either of them. Of course he wouldn't program in machine language. That's what compilers are for. And as for Cobol, he doesn't know how anyone can get anything done with it. It doesn't even have x (Blub feature of your choice). As long as our hypothetical Blub programmer is looking down the power continuum, he knows he's looking down. Languages less powerful than Blub are obviously less powerful, because they're missing some feature he's used to. But when our hypothetical Blub programmer looks in the other direction, up the power continuum, he doesn't realize he's looking up. What he sees are merely weird languages. He probably considers them about equivalent in power to Blub, but with all this other hairy stuff thrown in as well. Blub is good enough for him, because he thinks in Blub. When we switch to the point of view of a programmer using any of the languages higher up the power continuum, however, we find that he in turn looks down upon Blub. How can you get anything done in Blub? It doesn't even have y. By induction, the only programmers in a position to see all the differences in power between the various languages are those who understand the most powerful one. (This is probably what Eric Raymond meant about Lisp making you a better programmer.) You can't trust the opinions of the others, because of the Blub paradox: they're satisfied with whatever language they happen to use, because it dictates the way they think about programs.
- ominous_prime 13y agoI'm not sure what your point is, whether you think go is simple and powerful like lisp, or the new java, but simply quoting "The Blub Paradox" makes you sound pretentious (on a site where the largest percentage of readers are probably already familiar with said essay nonetheless). I don't think this is really applicable to the article anyway, since it's an article commenting on two very different languages and programming styles, not about being satisfied with a Blub.
- 13y ago
- VeejayRampay 13y agoFor the love of Thor, please provide a few code examples illustrating the content, hard to get an idea of how to simplify things with Go with mere words and ideas.
- Dylan16807 13y agoDefinitely. I'm left with no idea how Go actually helps. You can trivially implement 'pipelines' in any language by making a handful of queue structures and using them to feed your functions. Why were there callbacks in the first place?
- zerohp 13y agoMy thought exactly. The whole thing strikes me as a case of: Have a hammer and everything looks like a nail. First with callbacks, and second with channels.
- joe_the_user 13y agoYeah, It is quite hard to read a stream of text about programming without examples. But reading it, it seems like his problem could be more with Perl, which certainly has a reputation of supporting and encouraging unnecessary complexity. But argument is so vague, you could write the same article with Python substituted for Go - at least as far as the knowledge the article gives one about Go goes.
- gpvos 13y agoHmm, up till now I though Go wasn't anything special, but now I'm certain I will check it out.
- stcredzero 13y ago> A straightforward solution of the problem is superior to one that makes you feel like a high priest for having discovered it. It is also much better for the team and the company. Beginning musicians are just trying to play. Intermediate musicians are try to play as fancy as they can. Master musicians play what's needed by the tune. It takes somebody who's past all the ego issues to devote their intelligence to making code look simple. It takes great intelligence to solve a complex problem in a way that looks simple and straightforward.
- deleted 13y ago[deleted]
- mwcampbell 13y agoReminds me of this old Zed Shaw essay: http://zedshaw.com/essays/master_and_expert.html http://zedshaw.com/essays/master_and_expert.html I think at least two of Go's designers, Ken Thompson and Rob Pike, are true programming masters. Note: When I posted this comment before, I accidentally pasted the wrong URL.
- gngeal 13y agoI’d love someday to hear a young coder tell a story about someone they idolized like, “There was this guy I worked with who once optimized a complicated red- black tree getting 300% performance boost. I was baffled and ask, ‘How’d you do that? That’s impossible.’ To which he responded…” “‘That’s my linked list my son.’” I believe that this is exactly what Niklaus Wirth did in the Oberon compiler.
- stcredzero 13y agoYou sure it wasn't skip lists?
- gngeal 13y agoNot unless he had a TARDIS at his disposal. I mean, skip lists were discovered in 1989, and by that time, the Oberon compiler had already existed for a few years. I don't recall the source now (I'd have to dig for it) but I believe that the Wirth anectode referred to his intervention in a case of overzealous students some time before that.
- Vendek 13y agoCongratulations, he realized the advantages of monadic composition of computations.
- fixxer 13y agoClever is not smart. Consider this anecdote: I recently put together a DIY 3d printer. I didn't have the right tools to cut steel bar, so I made a clever jig and used a shitty Dremel without enough clearance. Clever? Yes -- it got the job done with limited resources. Smart? No -- dumb, actually. Smart would have been driving 15 minutes to Harbor Freight to buy a $20 cut-off saw.
- henrybaxter 13y agoSmart might be to buy a cut-off saw. Brilliant would be to find a working cut-off saw with blade for $20!
- jlgreco 13y agoIf he has an air-compressor already, he could do it for under $20. Air tools are pretty damn cheap on the low end. ;)
- orangethirty 13y agoI disagree. Brilliant would have been renting one for the day, or borrowing it from a friend.
- obviouslygreen 13y agoPerhaps I'm reading this wrong, but if I'm not, it seems to be making a great point but missing a far greater one. This is the more important lesson. Replace clever code with unremarkable code. Go has nothing to do with it. PERL has nothing to do with it. Switching languages most certainly has nothing to do with it. Keeping yourself in check and stepping back from your problems to understand their fundamentals, then looking for more appropriate and elegant methods of dealing with them in any language is what does this.
- mc-lovin 13y agoThis article didn't make much sense to me. In particular, what was it about the problem that prevents having a "stage" object with a "do_stage" method, which takes the input object and returns the output object (or some error code etc.). I feel like the answer has to do with concurrency but the description in the article was to vague to get a more precise idea.
- cgag 13y agoIt's so strange to me that people describe things like higher order functions and map/filter/reduce as being clever / complicated and think manual iteration and indexing into an array is "simple". I hate to keep linking to this talk because I don't want to look like too much of a clojure fanboy, but I think a lot of people would benefit from re-examining their definition of simple: http://www.infoq.com/presentations/Simple-Made-Easy http://www.infoq.com/presentations/Simple-Made-Easy
- jstelly 13y agoAgreed. This is a wonderful talk for anyone who writes code in any language.
- deleted 13y ago[deleted]
- mietek 13y agoSo, Go has message passing. Just like Erlang, since 1986. Only without per-process heaps, which make crashing processes safe. And without process linking and supervision, which helps systems built using Erlang/OTP achieve nine nines of uptime. Instead, it includes null references, also known as Hoare's Billion Dollar Mistake. But it's not enough to scorn the industry; Go's designers also look down their noses at academia. A modern, ML-derived static type system? Generics, which would enable the unwashed mashes to write their own `append`? Ain't nobody got time for that — wait, what? Oh, Rust does? Go's tooling is fantastic, and its pragmatism is commendable, but ignoring the last 30 years of programming language research is not.
- sp332 13y agoThe only reason Go doesn't have generics yet is that Rob Pike hasn't found a system he likes. He's not against it being added in the future.
- mietek 13y agoI haven't seen him comment on generics in languages other than C, C++ and Java. See also below: https://news.ycombinator.com/item?id=5821027 https://news.ycombinator.com/item?id=5821027
- sp332 13y agoMy info came from this thread https://news.ycombinator.com/item?id=5792842 https://news.ycombinator.com/item?id=5792842 which, now that I think about it, appears to be a bunch of second-hand info about the golang mailing lists. rsc posts here about golang sometimes but I don't think he's mentioned generics specifically.
- mietek 13y agoPerhaps Russ Cox will respond here: https://news.ycombinator.com/item?id=5796206 https://news.ycombinator.com/item?id=5796206
- 13y ago