So, maybe I just don't understand what you're suggesting. JavaScript may be the most successful language in history; it wouldn't surprise me to find that there's more lines of code in JavaScript today than any other language (possibly by a wide margin), even counting the billions of lines of C/C++ code out there that we don't see because it never makes it to Github or whatever. If it's not true today, it seems likely to be true within a few years.
Although I'm strongly anti-OO and hate Java with a passion for going all-OO, Java is a much better designed language than Javascript. And I think that sentiment is common enough that Javascript could become less relevant now that WebAssembly has entered the game.
Which is interesting because it's not that good a language, but circumstances and "luck" put it in the position it's in.
Not unlike a lot of successful companies.
When you look at why JS lost its way it changed too quickly, python changed in a non-backward-compatible way, ruby changed quickly (as did all its packages).
Very good insights there, the idea that when you buy into a platform you buy into the values of its community.
Interestingly enough it's why I didn't buy into the node.js's community. From interviewing people and talking to them at conferences and meetups somehow nodejs fans were both the most excited yet didn't really know what they talked about. Either one of those characteristics are ok, but both at the same time are hard to stomach. Then all the public scandals that seem to have node, also makes it hard to buy into - that pronoun scandal, io.js fork, another fork (ayo?), left-pad-gate.
A lot of good came from io.js (modern V8, promise integration etc). Ayo are working on interesting stuff like shared-memory workers for CPU intensive stuff.
The left-pad thing was indeed strange, but it could have equally happened with most package manager - and NPM improved for it.
Newbies being excited about something is the hallmark of a popular platform. Node.js feels like this as it graduated from a "fun project" to a popular web platform.
I think most stacks have competent and incompetent developers - making Node.js accessible is a good thing, even if it means there are more new people. At the Node.js project we're really fine with those and some "newbies" turned out to be pretty great programmers.
full disclosure: I am a Node.js collaborator.
But it was far more likely to happen in Node than anywhere else, for the following two reasons:
1.) Javascript has a tiny stdlib relative to other languages that are also used for "real work". I make that distinction just to rule out LOLCode/etc....
2.) NPM makes it so damn easy to add dependencies, both for finished products as well as component packages themselves.
#2 came about because of #1, and is honestly the only way that Node could have gained traction. So while it's NPM's fault you can't really blame them for making that choice.
A month or two ago I wanted to add a single NPM dependency to a project at work. I knew it built on top of other packages, but when I installed it I ended up somewhere between 690 and 700 dependencies. From typing `npm install {one-specific-package}`.
Python - it's a very large community. Given its size it's pretty diverse and also mature. It had some drama around an incident at Pycon a few years back and around the 2 -> 3 transition. Also Pycon is probably one of the most fun tech conferences.
Erlang - it's an example of a great small community. A lot of knowledgeable people. It has been around for about the same time as C. A good mix of people who have been involved in the community for 30 years and newcomers. There is almost no drama, people might disagree but that's ok. Sometime someone said something that was taken offensively in the online discussion, and the person apologized and everyone moved on. No forks, no backstabbing, voting anyone out and so on.
Elixir - probably my favorite example of wonderful community. And here all credit goes to Jose Valim and others on the team. They specifically focused on making the community warm, and welcoming for new people. That means not just codes of conduct but great documentations, good help and support online, tools to get started to write tests and so on. Also as a nice benefit they also in a way a part of the Erlang community as because there have been a lot of cool new fixes and features they've submitted for BEAM VM over the years.
So depending on what you'd be interested in, I'd pick one of those. No doubt there are other great communities (I suspect Rust is one) I am just not as familiar with them so this is definitely not a exhaustive list or a ranking, just my personal experience.
I can also second the node async library not being amazing to work with. Before version 2.0 of the library, some of the functions (filter, detect, every) wouldn’t propagate errors.
You can read about that here:
https://www.joyent.com/blog/post-mortem-debugging-and-promis...
https://gist.github.com/misterdjules/2969aa1b5e6440a7e401
Let me provide an example:
asyncRequest().then(value => {
var intermediateValue = 'foo';
return null.thisIsAnError;
}).then(_ => console.log('success!'), err => console.log('error!', error));
This program contains a programmatic error, but Promises make it look like an operational error.Why is this bad? Because it prevents you from doing post-mortem debugging of your program. No matter what you do, you can't access intermediateValue after you noticed the error..
Promises catch all exceptions thrown inside callbacks, which makes debugging (especially post-mortem debugging) harder. I've personally encountered this problem.
Couldn't this be solved by dumping all values in the scope the exception was created? Ie this sounds like a VM feature request, rather than a limit of Promises.
I don't know much about Go (I use .net mostly), but would be curious to hear some reasons to choose it over JVM/CLR.
The Good:
* Performance. Java and the JVM are certainly performant once things get going, but Go and other compiled languages are at peak performance out of the box. Go should generally be a bit faster or equal speed to Java and should use a fraction of the memory. Here's some microbenchmarks that look good for Go vs Java: https://benchmarksgame.alioth.debian.org/u64q/go.html
* Concurrency. Go makes it simple to communicate and synchronize with other threads, and the co-routine model allows for expressiveness in async without running into callback hell.
* First-class Functions. Some JVM languages have this, but even Java 8 doesn't have the ability to set a variable equal to a function definition. Coming from Node, Python, C, C++, etc. Making functions first class citizens helps a lot.
* Interfaces. Go has auto-fulfilled interfaces that you opt-in to by writing the functions they require. The compiler figures out which types match an interface for you, instead of you specifying it. This is probably my favorite feature of Go. It feels like duck-typing with type-safety.
* Unicode support. Go has excellent unicode support, which I don't think any JVM language has. Javascript also has great unicode support. This is probably a big one for someone doing a lot of web-based application deployments.
* "Batteries included". Go's standard library is amazing. All the basics you'd expect like string manipulation and math functions are there. They also have a dead-simple http server/client that supports http2 and SSL. Full crypto libraries with key-management. Encoding/Decoding for csv, json, and xml built into the standard library, even compression formats. The standard library feels really good to use compared to C++ and Java for me. C# I believe is on-par with Go as far as built-in libraries go.
* Compiled and statically linked. Go only does static linking for Go code, and does interoperate with C (but it's awkward). This means you compile the Go program and then run it, the runtime is in the binary. There's no worrying about versions of your JVM and ensuring that class paths are set up correctly. A single binary executable is all you need and what you get out.
* The tool chain. Go comes built in with documentation generation (really nice stuff, everything on golang.org/pkg is automatically generated from the source and comments), testing facilities (including coverage tools and benchmarking), and dependency gathering (like pip without the versioning). The dependency gathering uses VCS, so you can point it at any mercurial, svn, or git repo and Go will go download and put it in the right spot for you. The compiler can do cross-platform compilation from your local machine (on windows machine, compile for linux) with some playing with the settings. There's a race detector, code formatter, and version upgrade tool in there too.
The Divisive:
* Error handling. A lot of people I've seen using Java/C# like exceptions for error handling. Go doesn't use exceptions except in exceptional circumstances (and no try catch when that happens). Go instead recommends you use secondary return values (since you can return multiple values) for your errors. This leads to a lot of code that says `if (err != nil) { return nil, err }`. I find that in my first pass, that line is everywhere, but when I start building toward production of the system, I'm responding to the errors fairly deep in the call stack and the number of default error lines drops dramatically. Your mileage will vary.
The Bad:
* No generics. This might be a deal-breaker for you, depending on how you like to program. Go has first class support for a simple hash map (generic) and dynamic arrays (with slicing semantics similar to python) (generic). Every other generic collection type you might want will be made yourself, made by code generation with a third party module, or lacking any type safety through the use of `interface{}`. Generics are probably going to come at some point, but not yet.
* Package version management. While Go makes it easy to get the latest version of a package, Go does not have a robust package version management system yet. Getting the specific version of a package your project needs is difficult and error prone at times. Third party tools are currently the best way to deal with versioning and freezing your dependencies. Hopefully the `dep` tool or something like it will become a first class part of the tool chain, but it's not there yet.
* Debugging and IDE support. There's still not a lot of IDEs that support Go, but it looks like JetBrains may be fixing that soon with a dedicated IDE: https://www.jetbrains.com/go/
* Lack of expressiveness. In Go, there is often only one way to do things. Go is specified in it's entirety in under 30k words. You can write a whole compiler based on that information. That means it's lacking a lot of nice syntax that's become popular: Option types, pattern matching operations, decorators, lambda expressions, etc.
That's a tricky one. Right now it's wonderful, because all the included core modules are recent and relevant. I suspect in a decade you might find that the core modules are somewhat more crusty, sometimes support defaults that don't necessarily make sense with what's the common standard at the time, and is hard to change because of backwards compatibility. You might find in a few years you're not using the built in SSL library, or the http2 implementation, because better (either through capability or interface) alternatives have come about, and the core libraries start to look really annoying as you have to continuously tell new users to avoid them in lieu of the current best practice, which is not in the core libs.
It's a trade-off these languages make when designing their core libraries. There are upsides and downsides to both approaches, but one isn't necessarily clearly better than the other overall (even if different approaches have stronger outcomes when the language is new and when it's mature).
Eh. Go certainly starts out faster and is faster in some benchmarks, but in most workloads Java is faster.
> but even Java 8 doesn't have the ability to set a variable equal to a function definition
Function<Integer, Integer> f = x -> x + 1;
> which I don't think any JVM language has.Java (and so all JVM languages) has had Unicode support since at least 1997.
> The standard library feels really good to use compared to C++ and Java for me
I think you haven't seen Java's standard library recently.
> The tool chain.
This is one area where Java is ahead by a large margin in almost every single component you list.
For me, Go shines for small applications, and especially small command-line tools, for which the JVM is not a great fit. It's easy to learn and get started with, and the deployment is convenient. But for anything big, Java wins hands down, in robustness, ecosystem, debuggability and serviceability.
Most importantly, I believe it was very instructive for Bryan Cantrill: when he used JavaScript to develop the front-end for the Fishworks storage appliance he thought JavaScript was the new cool, and after this, it certainly appears that he came around and realized all is not that well as it seemed in the world of web development and JavaScript. Glad to see a person I deeply admire being willing to reconsider or at least re-evaluate their position as shaped by the new experiences.
More to the point of the talk: this is why I will never accept Linux, and Bryan spells it out to me why that is the case: I do not want to, and will never share nor live by the values of the people in that community, whereas I live by the values that the illumos and SmartOS communities espouse.
ES2015 is a pretty good language and its inherently asynchronous nature makes it ideal for UI.
Python's synchronous programming model makes it much more effective for back end.
When I started an AWS Lambda project recently I started with JavaScript and then thought "why am I torturing myself?" and switched to Python and never looked back.
At the front end, it's a real pleasure to use ES2015 although there's plots of room for improvement, which I guess will come over time.
I value freedom, but I value other things more. As the talk mentions, that doesn't make me wrong. Stallman would suggest it does.
Here's some interesting reading, a search of HN comments about stallman being right.[1] You might not agree with every instance (and not every instance is indicative of the point), but seeing the submissions the comments are generally on does tell an interesting story.
1: https://hn.algolia.com/?query=stallman%20right&sort=byPopula...
Similarly in the discussion of promises. I have written a lot of code using promises---though not in Javascript---and it's fine to debug. Javascript just makes a mess of it because it can't decide on what world view it wants. Is it trying to become a modern somewhat-functional language, which is the direction Ecmascript, Flow, Typescript, etc. are going? Or it is a primarily imperative language? If you go for the former you have very different expectations about how the language operates than the latter. It's notable that most functional programmers (which is my day job) don't make much use of debuggers and the kind of tools the speaker talks about building are not generally valued that much.
Now I don't want to give the impression that I think the speaker's world view is wrong. It's just different. Notable though is that we would have fundamental disagreements in how we view the world. It's not that we value, say, simplicity differently. We disagree on how simple is even defined.
> We cannot know if a thrown exception in a Promise is going to be caught or not
Bryan could you explain this? If you catch exceptions, or handle uncaught exceptions, it'll be caught.
process.on('unhandledRejection', function(reason, promise) {
console.log(promise);
});
If programmatic errors were not exceptions as you wish, what would they be instead?If you forget to handle an asynchronous error in Node.js by default it will silently fail (forget to check err in (err, data)). If something throws synchronously the process will crash so if I find an endpoint that does a `JSON.parse` in your server and pass it invalid JSON - I can easily do a DoS.
With promises, you drop the incorrect assumption that operational === asynchronous and acknowledge that things like `JSON.parse` can cause "operational" errors too (and asynchronous errors can be caused from programmer errors).
With promises, both synchronous and asynchronous operational errors are handled in the same way - nothing is swallowed and everything is reported. Except for extreme edge cases you get your core dumps - and debuggability is actually much much better because you have real stack traces and errors.