A year with Go
vagabond.github.io
vagabond.github.io
I was able to implement the service per the provided spec in 179 lines of Go in about ~2 hours. Stress tests passed. The job is done. We march on.
Could I have written this service in C++? Absolutely, but it would have taken me 20 hours to get to the same level of confidence. Maybe some could do it on 2 hours; I'm admittedly not a great C++ developer or frequent user.
Could I have written it in Python? Sure, but I would have had to scale and put it behind a load balancer, adding complexity to get equivalent performance.
From what I've seen of Rust, I like it and plan to give it more time now that it is stable. I haven't spent time with D. I played with Erlang. I don't care for Haskell for anything remotely related to "work", but I don't dispute that it has a place in computer science.
In my 2 years with Go, this is not my first positive experience. I have found that Go works well for cranking out high fidelity, snappy services like this. I think this is the result of the language's constraints enforcing simple patterns. Unlike C++ and Python, there are not a huge number of ways to accomplish tasks (at least not ways that feel natural).
Take it or leave it, but I like Go (for certain things).
Probably. C++ productivity really relies on knowing good libraries, and having the freedom to use them. Without details, I'd wager you could have done it in 300-400 lines. If you gave a brief overview of what you needed, I'd describe my first instinct for doing it in C++.
> If you were a strong C, C++, Java, Scala, Clojure etc
> developer you could equally deliver a highly scalable
> solution in 2 hours.
I guess the point is, no, you couldn't. An equivalent solution would be less robust/reliable or take (much) longer. Or both. > With some of this languages it would have been much
> faster AND much more reliable.
I don't think that statement is validated out by the body of evidence we have about Go. But, this is all hypothetical, anyway.Why not? Haskell seems perfect for this task. It has fast, robust and safe concurrency and GHC's IO manager is highly optimized and insanely fast.
Building with vanilla cabal I might have some issues, but professional haskeller's use the tools mentioned above.
cabal update && cabal install stackage
Building project:
1. clone a project, cd into it
2. stackage sandbox init
3. cabal install --only-dependencies
4. cabal configure && cabal build
If you already used some "lts version", you can put "stackage sandbox init lts-2.4" to second command and it will re-use existing lts-2.4 sandbox without a need to reinstall anything.
That's it. It takes a very long time first time you build with this with some version of lts stackage, and there is some movements towards binary package sets, but I'm not sure on status of that.
Not sure why you didn't compare to 2 languages at about the same level, and instead went with a lower level and a higher level language.
Well, sorry, but if that's your level of understanding after one year of Go, I'm furious I wasted time to read your article up to that point.
And when you define an object method (or I don't know how it's called when you do this:)
func (*string) uppercase(){
// make uppercase
}Then by saying you use a pointer means you will modify the value when you do this: mystring.uppercase()
So it's not really pointers, it's more an idea of pointers.
But as soon as you're talking interface, pointers don't work as expected anymore, because Go (at least that's how I'm explaining it in my head) passes magic interface values to functions. So you can't just change `func foo(s MyStruct)` to `func foo(s MyInterface)`, but rather you probably want `func foo(s MyInterface)`. Even though you are still explicitely passing a pointer when calling foo() and whatever you're doing with s inside of foo() is working on a pointer -- which your own function declaration doesn't even tell you anymore.
This is one of the things that confuses the hell out of me when using Go.
Take a step back and think about your statement...
Try adding /s in your head and read again...
I'm curious, though, as to how you could possibly think i was being serious. Do you spend a lot of time interacting with people with insane ideas?
See http://play.golang.org/p/ToRh0uK3zw for a demonstration.
Edit: Actually, you can call a function with a value receiver on a pointer value too, so this behavior is inconsistent =/
Can the author explain this bit some more? If adding mutexes slows down your code to the point where you would rather just deal with data corruption/races it seems to me that there are issues with your code, not the language.
(I have no idea how Go implements mutexes, though.)
http://en.wikipedia.org/wiki/Crash-only_software
Martin Rinard at MIT has done a lot of work in this area. It can be safe if you can rollback to a good state to avoid data corruption.
Glitch, my current project, does not bother with reader locks for multi-core execution; instead it can rollback and retry when a write-after-read is detected effects are logged (dependencies are traced so write-after-reads can be detected). It has performance benefits if you can amortize the book keeping overhead, and we need to do it anyways to support live programming (see: http://research.microsoft.com/en-us/people/smcdirm/managedti...).
It's not well designed -- lots of special cases reserved just for the compiler, some bizarro decisions, etc.
It's not modern (with the possitive associates of modern, not fadish, and modern being "the last 30 years of experience" which is still like a millenium in IT years).
It's implementation is not great either. Not a very good compiler, not a very good GC, not good tooling.
My theory is it caught on for 4 reasons:
1) It came from Google, and with some famous names to top. This got it initial publicity in programming sites and media, and Google then coughed for conferences, a spot on I/O etc -- so it caught lots of eyeballs, something independent languages don't have a chance to do.
2) It produces static binaries and this was a real need for lots of use cases.
3) It's easy to get started with, and made converts from scripting languages feel empowered, as if they were "real programmers" writing C, what with "pointers" and static types.
4) It makes writing parallel code for some uses cases easy, which is a good fit for some infrastructure/services apps.
(I don't think most teams outside of Google and some C++ or Scala shops have had any beef with "long compile times" for that to have been a major factor. Though it played to the hype of it being "just like a scripting language").
What is wrong with this? Exposing people to pointers and static types might give them confidence when writing or reading in "real programmers" code in C
I find the level of sneery nose turning in this thread quite abhorrent to be honest.
I don't see it as sneery nose-turning. Rather I see it as an acknowledgement that the real difficulty of C isn't pointers but rather is manual memory management, which Golang doesn't prepare you for.
http://blog.disqus.com/post/51155103801/trying-out-this-go-t...
Let's also not forget that Java is significantly faster, has every library under the sun, has a dependency system that actually makes sense and you have seamless interop between multiple languages e.g. Ruby, Python, Scala, Clojure.
Anyone who thinks Go is an upgrade to Java is woefully misinformed.
We shouldn't be under-selling how light the Go footprint is. In the long run it may be one of the few languages to compete with unikernels.
Can you please clarify what this means? I don't really understand what it would mean for a language to compete with a unikernel.
Citations please. While I am not necessarily saying I don't believe you (because a properly tuned JVM is lightning fast), making a statement like this without numbers to back it up is a gaping hole in your argument.
http://benchmarksgame.alioth.debian.org/u64q/go.html
Keep in mind this is comparing Go 1.4, I'd expect 1.5 to do better.
http://benchmarksgame.alioth.debian.org/play.html#java
The notable exception (not included in summary measurements) is the few tenths of a second run-time for meteor-contest. Of that few tenths of a second: JVM startup takes 95%, JIT and OSR another 4.9%.
Whatever kind-of app you have, you should take general statements about program performance with a grain of salt, there's even a page for that --
http://benchmarksgame.alioth.debian.org/dont-jump-to-conclus...
https://www.techempower.com/benchmarks/#section=data-r9
And arguably more real world than microbenchmarks.
Here's one example:
// imagine a for-loop around this
s := foo[i:i+4]
s[3], s[2], s[1], s[0] = s[0], s[1], s[2], s[3]
The reasonable assumption is that the second line generates either zero, one, or four bounds checks on s. However, the Go compiler likes to be sure, and turns it into 8 bounds checks.
I agree it's not a typical for a server to spend the majority of it's time swapping bytes. In the rare case that happens, you're going to hate the compiler for not being smarter.
EDIT: fixed formatting of the example
This is no surprise considering that go is a compiled language and the java garbage collector has had decades of very smart people working on it.
> It's an upgrade in terms of compile times, deployment simplicity, conciseness,
> concurrency, etc. Some people care about such things.
I remember the days of going for coffee while the compiler chugged away but I wonder what compiles people do on a regular basis that take such time? I just rebuilt SBCL here on a mid-2012 MBP and it took less than 6 wallclock minutes in the background including download and whatever else I was doing: real 5m12.752s
user 4m33.393s
sys 0m27.579s
I personally use D when possible, but waiting on compiles is usually secondary to the amount of time I spend thinking or exploring.Lack of an IDE is a feature not a bug.
Edit: or it is a symptom of a feature. No one has written one yet because they are happy with what they have.
> tooling
Do you mean you need an IDE that speaks the language to write anything efficiently? Do you mean your first day on the job is spent setting up tools?
Wrong philosophy in my opinion; I could imagine something better.
I worked full time for year without go to definition, mostly because full text search is almost as good most of the time, due to how regular formatted go code is. I don't really use anything else, mostly because I don't need anything else and I have better things to do than install editor plugins.
Languages with small clean syntax do not require that much IDE usage, at least this is my experience. I never thought my Erlang workflow could be improved with something like IntelliJ. I guess having a REPL helps a lot.
And I would never want anyone in my team who was doing major refactoring work without an IDE.
As a language, it's much less enjoyable to write. Yes, the concurrency primitives are much better, and that's a good programming tool. But to a developer coming from Ruby, code is often needlessly repetitive and obtuse to write. It ends up being overly verbose, full of copypasta, and much less expressive.
It's got it's niche – I've found it useful for writing small command-line utilities, and it's been surprisingly helpful at putting together a good deploy story for some work I've done on the Raspberry Pi (with the benefit of being well-structured and reasonably performant).
But I wouldn't like to use if full-time – mostly because it's just so weirdly irritating to write.
I think it helps to remember that Go's use case is a lot of teams interacting to produce fairly large code bases, i.e., at Google. I'm getting into it for my job because it has the same use case, and I find it hits a nice sweet spot in what you can do, vs. what you can't do, and I happen to be in a position in which I am routinely hit hard by other people's "clever" code. I don't do my personal coding in it, though.
Part of the problem with the "clever" code is that it often uses the clever features, but, wrong. Like, all the pain of seeing someone do something "clever"... and you'll note how I keep scare-quoting that... and none of the benefits. If the clever code was actually more concise and performant than my generally-non-clever replacements, I wouldn't mind so much, but it's amazing how often I rip out a "fluent" API or something and replace it with something simpler, faster, and still results in several hundred negative lines on the commits.
I've developed a theory that it isn't even because the developers are "dumb" or something, especially since in many cases they manifestly are not. I think it's that once you pass a certain size of organization, but are still sharing some code bases, you encounter an increasing number of instances where a developer has to fix something in the shared code, parachutes in to make the minimum possibly change that might work with the minimal cognitive effort, and gets out and back to their own code as quickly as possible. The net effect in such situations is that even if your code is being written by nothing but senior devs with decades of experience, from the point of view of the code being developed on it might as well be being bashed on by a series of above-average gorillas bashing away on keyboards.
Languages that tend to point you at a single right answer, and confine the very busy, very distracted gorillas from beating on the code too hard, and make it obvious when that's happening, can be advantageous in those cases.
No, that's not every case, but it's a useful one.
https://functionwhatwhat.com/go%E2%80%99s-type-system-is-an-...
If I would like to teach something smart to software engineers I use OCaml, if I want to teach how simple things can achieve a lot I use Go. (They gonna end up programming in Java or Python anyways :)) )
It has its quirks (what languages doesn't?) but it is a fantastic general purpose programming language.
I'm baffled by this. I've been deploying Java applications for years, and this has literally never been a problem. You build a WAR (or EAR, or uberjar, or distzip, or whatever). You install a JRE on the machine. You deploy. You're done. It's never been a problem for me, and it's not something that's talked about as a problem in the Java community, which suggests it's not a problem for other people.
When i see someone suggesting that Go has a significant advantage over Java in terms of deployment, i assume that they don't actually have experience of deploying Java apps, they're just regurgitating the standard Go talking points.
Then you set your memory parameters. Then you tweak them, to make it more performant. Then you increase them some more to make the GC work less. Then you hook up to the JMX port so you can profile what's going wrong, and identify some XML library as allocating megabytes of strings when it then dumps. Then...
Yeah.
The JVM has generally excellent performance with the defaults.
I would love to have a GC which tunes itself to accommodate the workload. On the JVM, G1 is a step in the right direction. How does Go's GC work in this regard - does it auto-tune itself?
Also, how are Go programs monitored in production? Are there tools like AppDynamics, NewRelic, JConsole or similar APM/telemetry solutions available to monitor Go applications?
I did once work on a system where we installed two JREs in parallel, and selected which one to use for the app based on an entry in the manifest file. That let us upgrade Java versions under application control, without requiring sysadmin intervention. Took a couple of lines of shell script.
That's two steps. The first one can ruin your day.
Just download it, copy it and set JAVA_HOME to make it easier for other applications.
I've done this on hundreds of servers during my lifetime and never once had an issue.
I think it falls solidly in the "easy if you know it, and a wasted q hours if you don't" category.
> You install a JRE on the machine.
Whoops. That's where you lost me.I'm not saying that library versioning and dependencies are not a problem with Go. Quite the contrary. But it's a compile time issue. There are far fewer surprises at runtime and that makes deployment a lot easier.
Java has multiple native code compilers, how is it a benefit when Java can do the exact same thing? (FWIW I learned recently that C# also has at least one native code compiler).
Golang is not an especially impressive programming language --- as a language. But it seems to me like it is an undeniably impressive programming tool.
Go's primary goal is: excellent tooling.
Since when was compile time an interesting aspect to judge a programming language? More in the "nice to have" category, especially if your program is not 1 million lines and/or your language's compiler doesn't provide some modularity in this regard.
"I don't think most teams outside of Google and some C++ or Scala shops have had any issue with "long compile times" for that to have been a major factor."
Put another way, much of the problem is "modern compiler optimization takes a long time". Go's solution was "remove the modern optimizer". That doesn't actually solve my problem.
Since compilers were dog slow.
When using irb or lisp or smalltalk, my productivity is off the charts compared with C++, in no small part to the compile time.
I contributed to Go in the early phases and I really enjoyed using it and learning it, but I found myself going to either Java if I wanted to write something for production or Node if I wanted to write something as a prototype. Unfortunately, I haven't used it almost at all for the past couple of years :(
I'm sure you're right about Rust, and that people will be down on lifetime annotation burden, painful compilation times, painful data structure nesting, the complexity of unsafe code, and other things, while forgetting all the times things are actually easier, more performant, and safer due to all that language support.
I see it as a natural damping curve: at first things seem peachier than they really are, then they seem much more frustrating than they need to be, then you come to terms with their unique trade-off of strengths and weaknesses. What I would like to know – if anyone here has discovered such a thing – is a way to skip to the last step more quickly.
Unfortunately, most of the debate around languages involves "philosophy", where there's little objective measurement that can be done: composition vs. inheritance, the effect generics have on readability, whether immutability is a better way of reasoning about data, whether namespace syntax should use double-colons or periods, and so forth. These debates are endless but don't strike me as very useful: the exact issues that get brought up and argued on HN have been going back and forth largely since the '80s if not earlier, and they're neither interesting (because we've made little progress on consensus) nor relevant (since people who actually need to choose a language based on its merits will choose it because it helps their job, not because of philosophy).
It's easy to bitch about things the way they are now, but understand there are people and technologies who were around before you arrived on the scene and in general, things are consistently getting "better", for all subjective interpretations of "better".
Maybe that means it's not a hive mind? Different people have different views, I suppose.
But my first project in a new language will take more than an hour (well, "hello, world", but that won't be enough of a test), and after I find something I don't like about the language in a first project, I've either found something bad about the language or something bad about me that this language is going to cure. Which is it? How will I know without an even bigger project...and pretty soon I'm the OP having spent a year giving the language a fair trial and now needing to start over with another language for another year.
I have a lot more hours left to investigate restaurants than years to investigate languages.
So, it's not a question of "fashion" per se, but trying to learn from the experiences of others. Of course, "others" vary, but you can still learn a lot about things that wouldn't be obvious to you in a first project by reading a lot of those varied opinions.
I read a lot about Go that interests me, but I just saw a survey of several thousand back-end mobile developers that showed that now, after several years of availability and the Google connection and all the talk about being a better Python and its explicit positioning as optimized for server-side apps, Go was not among the Top 8 most used languages for server-side apps. That interests me, too.
In his blog post written roughly a year ago about his first week using Go he says this:
> gonna be dealing with Go for a while and will have to make the best of it.
I could be wrong, but I get the impression that if it were solely up to him the project might have been written in Erlang either from the start or after trying Go for that first week.
Generally, trying to approach Go from any perspective related to PL theory is bound to be fruitless, primarily because the context of Go is that of Rob Pike's gradually evolving research languages, which have always been imperative, based on a few primitive constructs and having some form of CSP-like concurrency model built in. Much of it overlaps with principles explored in Plan 9 and Inferno, where holistic systems thinking has been the norm, and so Go makes sense as a language built by systems hackers used to dealing with infrastructure, rather than being conjured from the academic PL scene.
Much as Alef superseded Newsqueak, so Go has superseded Limbo.
In general, it's much easier to spot defects and more difficult to see the good in things. People are much more likely to play into their own biases from the safety of online anonymity.
For instance, "I don't like this OS, browser, language, editor, hardware, etc or this person's/company's choice of OS, browser, language, editor, hardware, etc, therefor downvote/rant/complain/FUD."
It's really too bad. It never hurts to know more, and it shows new members of the community that it's acceptable to behave that way and to not try to learn new things.
At least this guy actually used it for more than an afternoon... Though anyone who says they don't understand go's pointers after that length of time is a somewhat questionable source.
I've been using go full time for two years and love it.
Tip: you're not required to be a defender/evangelist.
The HN guidelines were changed (or defined more precisely...) and many people might shy away from posting negative comments about submissions.
I have to compliment the author on omitting complaints about lack of generics.
And if you wanted a concurrent language that wasn't a functional language what would you use?
With Clojure, Scala or F# you need to be disciplined and don't really get many guarantees, but you can reuse lots of imperative code.
It kind of depends what your priorities are, if it's correctness or development speed.
In my experience creating Haskell bindings to say imperative c libraries is pretty easy. What imperative libraries have been hard to access for you personally?
Well yes, I can just live without imperative libraries because it is so natural to have single assignment (in the same scope) that I do it even in other languages. Accessing imperative libraries is possible though, just think about the C libs. What would you implement in Erlang the imperative way or which library do you miss exactly? The ecosystem is definitely smaller, but you can get support, some of the smartest software guys hang out on the mailing lists and IRc as well. I got absolutely amazing help from both when we worked on a Erlang project.
> It kind of depends what your priorities are, if > it's correctness or development speed.
Yeah and also how much fun you want to have. :)
Using Erlang is great but not many devs out there for hire, on the other side you have two seasoned Erlang devs they can do a lot. Contractors FTW!
Btw. what about using ASN.1 with Erlang? How does that change the correctness / development speed?
As far as I know Erlang doesn't give you any guarantees about side effects. You can call side-effecting functions at any point in your program, just like in Clojure or OCaml.
Of course, the elephant in the room is needing a windows-based infrastructure ... but if that's not a huge barrier, it's not an unreasonable choice.
What makes you say this?
Being a "boring" simple language with limited options for implementation means more focus on the problem and less on the infinite number of ways to solve the problem "elegantly". But there are a lot of other factors too. Static typing helps once the code base gets above 5000 lines, for example. Fast iteration from making a change to running the tests again also helps.
In my day job I use Haskell to "just get shit done". However when it comes time to refactor I can do it much faster and safer in Haskell.
The ease of refactoring creates an incentive to improve code.
At least that seems to be what has happened in my case.
In the interest in figuring out which, what problems do you work with and what are your principles/beliefs/guiding principles in software? :P
And it's true because its creator says so right here, in this link!
And I bet you're going to say "But he coined the term!". Yes. He's still making up his own definition twenty years after the industry gave its own, so whatever he says on the topic is moot.
Firstly, I don't know at what exact point did Kay come out in demystifying OO (1998 or so?), but the design principles of Smalltalk and messaging date back to publishing in 1974, with many references to it afterwards.
Secondly, the idea that there is one singular definition of OO that the industry has standardized on is absurd. Object models differ semantically from language to language, even if some general motif of "encapsulation/inheritance/polymorphism" is present (though again, important subtleties abound - is encapsulation enforced or merely convention, how structural and nominal subtyping are modeled [mixins], etc.).
But would you say that's the definition of OO? In fact, Kristen Nygaard who was the creator of the Simula language, an ALGOL extension, and now considered to be the first OO language (semantically in that it beefed up structs and other procedural nuances) considered object orientation to be a property of any system in general as opposed to language constructs. Thus, Erlang definitely does count as OO under that, too.
So what definition do we follow, then? Who do we trust?
Apparently this is a difficult problem: http://c2.com/cgi/wiki?DefinitionsForOo
But by all means, Erlang embodies many OO design principles by certain important taxonomies - both Nygaard's and Kay's. If you're going to reject both, then you're going down murky waters.
That's interesting because Armstrong himself thinks that OO sucks:
http://harmful.cat-v.org/software/OO_programming/why_oo_suck...
But what they didn't know and couldn't prevent, was that their world would soon become (neigh, has already become) the battle ground of 3 ultra-advanced warring alien species: Go, Rust, and Elixir. Backed by unimaginably powerful forces (except Elixir, which is just open-source by Poland's own Jose Valim), the upstart alien languages threaten to herald in a terrifying future for the current 3 powerhouses.
OP's article, and the fact that lots of people are agreeing, is a sign that one of the invading aliens is weakening.
What about Pony?
C, C++, Java, Python, and an appreciation of formal specs over frameworks form Go.
Most languages to perform professionally in you have to know what not to do (not use C++ templates too much, not give into verbosity in hierarchies in Java, not use the GIL, etc.). In Go, because it is a relatively clean refactor, you don't have to worry about this.
But you do have to invent your own smaller libraries for what you want to do sometimes. Because it's a younger language. This is good though if you like programming and stacking lego pieces on you way to stacking paper.
Go certainly taught me quite a bit about closures and programming to an interface.
There is nothing special about Go. It's simple and just works.
Every time I used Go for a project it just worked. No fuss. With very little effort. And that's the point.
Go is interesting as a replacement for a scripting language, perhaps. But it seems very lacking in many other areas. All of the points in the article, plus what libraries are available.
I think some of it could be explained by it being a young language, but if that's the case, why is it getting the adoption it has so far? Just because it came from Google?
Go is the poster child for Worse is Better. It's ugly, inconsistent, feels naughty at times (all those copy-pastes ! It's so un-DRY !) but it gets shit done.
This post got me to have a second look at Elixir and I spent the whole day going though its documentation and prototyping an idea I wanted to implement in go, specifically because of go's concurrency model. And frankly ELixir is exactly the right fit for me, not only for this case but generally as a language with the kind of elegance and expressiveness I'm drawn to.
Then you can use Ctrl-f (Cmd-F on mac) search built-in browser to look for things.
It doesn't work for large repositories but most of them aren't.
Agreed. C and Rust are systems langauges, Go is not particlarly great in that category. That is okay.
I will say, I hope you have fun getting an average CS graduate to properly write and maintain a Haskell or Erlang program with concurrency. Go is stupid easy to pick up for anyone who has worked with C/C++/C#/Java/Python/Ruby, which, by no exaggeration, probably encompasses every programmer alive.
Meanwhile, Haskell and Erlang look like gibberish to most programmers. And I'll admit, that's a lacking argument. Functional languages cannot be said to be bad just because most people don't understand the functional paradigm.
But the fact remains, an average programmer can sit down today with no knowledge of Go, and by the end of the day create a concurrent program using Go. And given the lack of flair in go, it's the langauge that lends itself to being maintainable. You won't see anything like in python or perl where you're almost expected to abuse the langauge internals (see this awesome example in python [0]). That's completely by design. [1][2] (scroll up to see the quote by Rob Pike)
If you have a team of a dozen guys working on a project with thousands of lines, your priority is not just performance (Go is quick enough [3]). It's probably not elegance either.
It's software that documents itself.
I used to work as a systems administrator for my schools engineering department. We would deal with fixing perl scripts dating back to the 90's. As students came and went, the result was hack jobs on top of hack jobs by students who are now in their 30's. I hated it. I would commonly have to rewrite scripts because over the years the basic flow of the program became completely asinine.
That's exactly where go does well. Go is a langauge for people who don't want to have to deal with abuses of the language that their coworkers put in place. Go is a language that understands that for programmers, maintaining code means fixing bugs and fixing bugs tends to boil down to hacky solutions. Go ensures that those quick fixes aren't hacks.
> "The only place I can see Go shining is for stuff like portable command line utilities where you want to ship a static binary that Just Works(tm). For interactive tasks I think it would be fine, I just don’t think it is particularly well suited to long-running servery things."
I really don't understand why he feels that way. I don't see the distinction.
> "It also probably looks attractive to Ruby/Python/Java developers, which is where I think a lot of Go programmers come from. Speaking of Java, I wouldn’t be surprised to see Go end up as the ‘new Java’ given the easier deploy story and the similar sort of vibe I get from the language. If you’re just looking for a ‘better’ Ruby/Python/Java, Go might be for you, but I would encourage you to look further afield."
This reminds me of The Story of Mel [4].
If you're someone who enjoys programming and are writing the code for fun, I agree. Find the most unique language and do it in the most elegant way. Programming is almost an art, and if you're trying to be artistic, unique langauges are great for it.
But not all software is artistic.
> "Good languages help evolve your approach to programming; LISP shows you the idea of code as data, C teaches you about working with the machine at a lower level, Ruby teaches you about message passing & lambdas, Erlang teaches you about concurrency and fault tolerance, Haskell teaches you about real type systems and purity, Rust presumably teaches you about sharing memory in a concurrent environment. I just don’t think I got much from learning Go."
I don't think that all langauges need to be learning experiences. Sometimes you just need to get shit done.
[0]: https://benkurtovic.com/2014/06/01/obfuscating-hello-world.h...
[1]: https://talks.golang.org/2012/splash.article
[2]: http://nomad.so/2015/03/why-gos-design-is-a-disservice-to-in...
You linked to someone intentionally trying to obfuscate Python as much as they can. Programmers are certainly not "almost expected to abuse the language internals". All dynamic languages provide various means for code obfuscation... it doesn't mean the language encourages obfuscated code. With the notable exception of Perl.
But it does allow it, and I think that means it inevitably creeps into a lot of code.
a.b = c
In isolation, there is really no way to tell what that line of code will do. Maybe it will simply assign c to a.b. But because Python has property setters, it might also update some rows in a database[1], write a file, or make an HTTP request.One might call that abstraction, but I think it qualifies as obfuscation. A single line can invoke arbitrary behaviour.
[1] This is how SQLAlchemy's models work. As I write this, the library is nearing it's 10,000th commit. A serious piece of software!
Isn't that true of any language with even the simplest mechanism for abstraction?
How about this go code?
doStuff(1, 2)
It could "update some rows in a database, write a file, or make an HTTP request."An example in golang would be something like:
type foo struct {
a string
b int
c *someOtherStruct
}
var blah = foo{"example", 42, nil}
blah.b = someMagicVariableIf there's any benchmark more pointless than the alioth benchmarks game, it's the 'what can a novice programmer do with the language in the course of 8 hours' benchmark.
There are zero businesses that operate by giving novice programmers 8-hour tasks in unfamiliar languages.
Just name-calling, ho hum.
type ExInterface interface { ... }
type ExStruct {
arr []ExInterface
}
Each element of arr need not be the same type, so long as it implements ExInterface. In Rust, the only thing I can do that is similar is: struct<t: ExTrait> ExStruct {
arr: Vec<t>,
}
Which means that each element of arr not only has to implement ExTrait, but also has to be of consistent type with the rest of the elements. If I want the same level of flexibility the Go gives me, I need to make an enum of each possible type that arr can contain.For more information on that, check out "trait objects" (http://doc.rust-lang.org/book/trait-objects.html).
The gist of the issue is this: a Vec (and most other collections) needs all items to be sized and of the same size in-memory to lay itself out (know how much memory to reserve for each item for instance), and it stores its stuff inline. So a Vec<u8>'s buffer looks like this:
[u8|u8|u8|u8]
and a Vec for a struct { u8, u32, u8 } looks like this (ignoring padding): [u8,u32,u8|u8,u32,u8|u8,u32,u8|u8,u32,u8]
If you want to store both A and B inline in a Vec you've got trouble: that they both implement Foo doesn't mean they have the same size at all (and they often don't), and Rust's type system doesn't allow it anyway (`A: Foo` says that A implements Foo, but the function or collection still gets an A via reification and monomorphisation).The alternative is to do what languages Java or Go do under the covers: add a fixed-size pointer as indirection between the collection and the actual items (the pointer is actually fat, you get a pointer to the instance itself and a pointer to the vtable for the trait implementation, I think Go does the same but java doesn't as each instance has its classpointer), so you get e.g.
[&A|&A|&B|&A]
all pointers are the same size and things work out. More generally than trait objects, you need to do this to store any unsized type (http://doc.rust-lang.org/book/unsized-types.html) in something which only accepts sized types. type StructOne struct {
field uint32
}
type StructTwo struct {
field uint64
}
It's pretty clear that these structures are of different size. Now, if both of these structures implement the "Foo" interface, we can't simply make an array like []Foo, since we'd have no practical method to index into the array. Go solves this by making []Foo actually be an array of pointers.However, Rust's philosophy is, AFAIK, "be explicit about the cost you pay". So, if you want to make an "array of things that implement Foo", you need to explicitly put the "things" behind a pointer, or a Box<>. So, you get:
struct MyStruct {
arr: Vec<Box<Foo>>,
}
Which makes it explicit that you're storing a "list of pointers to things that implement Foo". Of course, the nice part is that you can use generic syntax to make an array that doesn't use pointers, like so: struct MyStruct2<T: Foo> {
arr: Vec<T>,
}
In the above, you can only store items of a single type in the `arr` field, and the generics constrain that to be only types `T` that implement Foo. The upside is, however, that you don't have any pointer indirection (and the compiler monomorphizes - i.e. generates new code for each generic implementation), so your code is probably faster / easier for LLVM to optimize.Traits are types, though you need to put them behind a pointer (Box<Trait> or &Trait) if you want to use them as types; and this is dynamic dispatch.
You can use them in static dispatch (generics) too, and in general you should try to do that whenever possible. Plus there are loads of things you can do with them that Go can't (static trait methods, associated items, generics, etc)
The only feature that Go interfaces have that Rust traits don't is auto-implementation, and that's a misfeature IMO. It works okay for Go, but in Rust it makes more sense to explicitly say that you are implementing a trait.
Apparently, the author doesn't understand how pointers work in Golang. He should read this article: http://openmymind.net/Things-I-Wish-Someone-Had-Told-Me-Abou... . In short, golang pointer is neither c pointer nor java reference.