10 ms·
Relatively recently I've adopted the stance that JS (via V8+NodeJS) has the best feature set of the "scripting language" tier of interpreted programming languag
by hardwaresofton 8y ago
Relatively recently I've adopted the stance that JS (via V8+NodeJS) has the best feature set of the "scripting language" tier of interpreted programming languages, assuming ecosystems for your problem are comparable. The combination of compile time type-checking support (via Typescript), parallelism support (recently in v11 w/ worker threads), and built in async IO paradigms give Node a huge leg up over ruby, python, and perl.
Weirdly enough, JS is the best in my opinion precisely because it does so much to not be itself. The crazy iteration speed of the JS ecosystem means that people have done crazy things, but the good stuff has remained. Python relatively recently added typing[0], and Matz has mentioned that ruby has no plans to include types in the language proper (though people are working on it). Perl might be the closest in terms of features since it has thread support but...
If you enjoyed this hot take, here are a few others you might enjoy:
- "extensive" unit testing is a poor man's type checker
- developers that don't think specifying types is helpful are still early in their careers (those who suffered in the dungeons of Java get some slack)
[0]: https://docs.python.org/3/library/typing.html https://docs.python.org/3/library/typing.html
- raverbashing 8y agoWanna do typechecking in Python? Use pylint. No type hints needed
- dunefox 8y agoThat's a linter, not a type checker.
- jaabe 8y agoWe stopped solely using strong-types after decades of only doing JAVA and C#, and it hasn’t decreased our code-quality. I think most people who’ve spent a significant amount of time with strong-types do them by heart. We didn’t leave strong-typing to leave strong-typing btw, we just started doing more and more with Python.
- 01100011 8y agoLots of things work when your people and processes are good enough. We don't need seatbelts if we never crash. That can lead to problems with scaling your team if needed, however. At some point you might have to let a moron in, and stronger typing just might be the thing that prevents a catastrophic bug. I did Python for embedded systems for a year. Python is so expressive and well equipped, but the lack of pre-execution type analysis leaves you vulnerable to severe defects unless your testing coverage is 100%. I would prefer Java over Python just for the safety the compilation step provides(and I don't care for Java). I love programming in Python, but system reliability trumps my personal desires in this case.
- hardwaresofton 8y agoI'm sure you know this already but you might want to check out: - https://docs.python.org/3/library/typing.html https://docs.python.org/3/library/typing.html - http://mypy-lang.org http://mypy-lang.org Also flake8 has also helped -- it's just a linter but using it in conjunction with the typing module and running that in a watch loop in another terminal window has done wonders for me.
- 01100011 8y agoAnd that's awesome, but if you're dealing with a large legacy codebase it will take a while to annotate your code. I love flake8. Properly tuned, it can be a great help. It saved my butt more than once.
- hardwaresofton 8y ago> We stopped solely using strong-types after decades of only doing JAVA and C#, and it hasn’t decreased our code-quality. How do you know this? It's exceedingly rare that anyone actually keeps track and monitors rate of defects in any application, but there have been studies done[0][1] on the ability of stronger typing in languages to reduce errors. My condolences for your time using Java and C# -- they are often what people first consider when they think of languages with "good" type systems, but I dislike them both because what they introduce as "good" type systems are often very much not, in comparison to languages like Haskell. It's a bit disingenuous to act like Haskell has been a performant/production-ready option as long as those languages but still, almost every time I talk to someone and we get to the topic of typing I almost always assume that their bad experiences came from those languages. > We didn’t leave strong-typing to leave strong-typing btw, we just started doing more and more with Python. What are your opinions on https://docs.python.org/3/library/typing.html https://docs.python.org/3/library/typing.html ? [0]: http://ttendency.cs.ucl.ac.uk/projects/type_study/documents/type_study.pdf http://ttendency.cs.ucl.ac.uk/projects/type_study/documents/... [1]: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC2935596/ https://www.ncbi.nlm.nih.gov/pmc/articles/PMC2935596/
- AnaniasAnanas 8y ago> via Typescript null/undefined is an inhabitant of every type in typescript, I would suggest purescript instead. > Python relatively recently added typing I think you mean the ability to add explicit types to variable names. It always had types. > "extensive" unit testing is a poor man's type checker Certainly.. iff you use dependent types. > developers that don't think specifying types is helpful Why specify types if they can be inferred? Why do work that our computers can do for us?
- smt88 8y ago> null/undefined is an inhabitant of every type in typescript This isn't true as far the way you stated it. TypeScript types are not nullable by default. How can you use existing JS libraries without supporting null anyway?
- wwwigham 8y ago> null/undefined is an inhabitant of every type in typescript, I would suggest purescript instead. If you want absolute certainty in your types with TS, you should be using the `--strict` flag, which makes it so this is not the case.
- evmar 8y ago"absolute" is a bit of a funny qualifier to use here, given the many soundness holes in TS. For example (included with --strict): https://www.typescriptlang.org/play/#src=class%20Base%20%7B%0D%0A%20%20f(x%3A%20string%20%7C%20null)%20%7B%20%7D%0D%0A%7D%0D%0Aclass%20Derived%20extends%20Base%20%7B%0D%0A%20%20f(x%3A%20string)%20%7B%20x.charAt(3)%3B%20%7D%0D%0A%7D%0D%0Alet%20b%3A%20Base%20%3D%20new%20Derived()%3B%0D%0Ab.f(null)%3B https://www.typescriptlang.org/play/#src=class%20Base%20%7B%... (I like TS, I just don't think it fully solves this problem!)
- hardwaresofton 8y ago> null/undefined is an inhabitant of every type in typescript, I would suggest purescript instead. You're right -- but I've found in practice that strict null checking[0] is more than enough. Also I assume that Purescript has a similar bottom value as haskell[1] (please correct me if I'm wrong). > I think you mean the ability to add explicit types to variable names. It always had types. Yep -- I actually meant literally the `typing` module[2]. > Certainly.. iff you use dependent types. You can get some good guarantees with container types (`newtype` in haskell terminology) that are constructed in a very specific way, assuming you have immutable values. For example, defining some type `NonZero<Int>` in typescript w/ `private readonly` interior value. > Why specify types if they can be inferred? Why do work that our computers can do for us? You're right -- I misspoke (misstyped?). By all means if inference is possible that is also fine. Somewhat seperately, the statement stands as far as type signatures (i.e. `doThing :: Input -> Output` or `function doThing(in: Input): Output`) go -- they're great benefits to a codebase in my opinion. [0]: https://basarat.gitbooks.io/typescript/docs/options/strictNullChecks.html https://basarat.gitbooks.io/typescript/docs/options/strictNu... [1]: https://wiki.haskell.org/Bottom https://wiki.haskell.org/Bottom [2]: https://docs.python.org/3/library/typing.html https://docs.python.org/3/library/typing.html
- rtpg 8y agoI think that the language tooling is really powerful. I work in both Python and JavaScript, and I often miss Typescript’s power. I think Python still has big advantage in the libraries. The standard library is full featured and well documented. But perhaps just as important is that libraries are also really often high quality with clear documentation. I think there’s a lot of interesting JS libraries and experimentation. But I love not feeling a need for better Python libs, because they’re already so mature. I think that a “tidy verse”-style project in JS to offer a “proper standard library” across the ecosystem would do wonders for the bit of a mess server-side libraries are at the moment. Something that could be as effective as jQuery was at corralling DOM API . The Node.js APIs are good baselines but not super fun to use directly...
- int_19h 8y agoFor me personally, the huge turnoff for JS/TS is the library ecosystem, and specifically this notion that everything is better as a myriad of tiny 10-line libraries with a spaghetti dependency graph. Python is much more traditional in that it has a rich standard library to begin with, so most third party libraries are also bigger, and it's easier to track of what does what.
- evv 8y ago> a myriad of tiny 10-line libraries with a spaghetti dependency graph. I'm curious why people dislike this. I'd rather have lots of little decoupled libraries than huge monolithic dependencies that attempt to do everything in one big folder. The big libraries often duplicate functionality found in smaller tools, and I would rather they simply consume a bunch of small tools that can be shared across the ecosystem. It reminds me of the oldschool pre-systemd UNIX philosophy of "do one thing, and do it well". Did everybody change their minds on this?
- thaumasiotes 8y agoThe problems come in when one of your little dependencies itself depends on something else. You want a single level of dependencies. Monoliths are good for this because they try to be self-contained.
- fyfy18 8y agoRuby and Python have had built in support for threads since the beginning, and they both have 'community standard' libraries for doing async IO: https://twistedmatrix.com/trac/ https://twistedmatrix.com/trac/ https://github.com/eventmachine/eventmachine https://github.com/eventmachine/eventmachine (I guess Perl does too, but I haven't used Perl for 10 years) I admit the promise pattern may be simpler to understand, but if you need to build a heavily evented system Node doesn't provide anything unique that can't be achieved in other ecosystems.
- hardwaresofton 8y agoThis is right, but only with a very limited interpretation for "support for threads", which does not include actual parallel computation. Not only is there a problem with the GIL, the only "threading" that ruby and python support natively is the spawn-another-process-and-find-a-way-to-coordinate kind (ala multiprocessing[0] in python). Also, the async IO support via libraries are there for ruby and python, but that brought along with it significant fragmentation (at the very least in the python case, I know less about ruby) -- no one was 100% sure whether to use tornado, twisted, gevent/eventlet for a very long time. A quote from another comment I wrote[1]: >> If we really want to get in the weeds, we could talk about python 2.x's floundering around async IO -- IIRC Twisted/Tornado/Gevent/Eventlet were all close to equally good options (and thus mindshare was split) while node had it built in, with a virtualenv-by-default packaging system. Also there's WSGI -- the interoperability it provides is cool, but also means more moving parts than a simple node+express setup. [EDIT] - It's a little unfair of me to decry the fact that multiple good solutions existed as a bad thing when I'd say it was a strength of the ecosystem. I do think it's valid to discuss the issues with packages that weren't compatible across interface boundaries between these async io libraries though. > (I guess Perl does too, but I haven't used Perl for 10 years) Same here, it's been a similar duration since I've used Perl for anything but even back then, the major difference between perl and the others was extremely good native regex support and the ability to spawn system threads that actually ran in parallel without coordinating another process. > I admit the promise pattern may be simpler to understand, but if you need to build a heavily evented system Node doesn't provide anything unique that can't be achieved in other ecosystems. My point was about the ease of achieving it... In the last ~3 years I've seen a wave of articles in the python blogosphere about how to properly use asyncio and all these new async-enabled libraries pop up (the old ones that relied on twisted/eventlet/whatever else are still around of course and perfectly good) -- what I'm saying is that JS has had this since the get go, and it's been thrashing python/ruby on benchmarks that favor the usecase for the same amount of time, especially if someone doesn't use one of the appropriate libraries. NodeJS's async io story is "batteries included", and that's huge in this day and age. Whether node has the right interface or if they made it ergonomic enough is a whole 'nother thing though... [0]: https://docs.python.org/3/library/multiprocessing.html https://docs.python.org/3/library/multiprocessing.html [1]: https://news.ycombinator.com/item?id=18756083 https://news.ycombinator.com/item?id=18756083
- tokyodude 8y agoIf I have to run a transpiler it's not a scripting language
- GhostVII 8y agoIs python not a scripting language because some versions of it are compiled?
- deleted 8y ago[deleted]
- adriveatrain 8y agoimplementations are not languages
- tokyodude 8y agoscripting language to me has a definition. Maybe I made it up but my definition includes "runs immediately". So, basically, any language who's most common usage is either via "#!/bin/path-to-interpreter" or "interpreter script" or register some extension ".bat" in DOS/Windows This fits python, perl, sh, node It does not fit C/C++/C#/F#/Java?/Go/Swift/Typescript. Those are 2 steps at least. One to compile which generates an executable. Another to run the executable. But I'll acknowledge I made up that definition. No idea of others agree. I get that it's arbitrary. I could certainly make something that given "#!/bin/execute-c-as-script" takes the .c file, compiles it to some temporary place and runs it. But that's not "most common usage" so I'll stick to my point as part of the definition of scripting languages. For me, if it's most common to have a manual compile step separate from a run step then it's not a scripting language.
- regularfry 8y agoIt's basically meaningless when you try to line languages up with that sort of criterion. Go compiles fast enough that you can use it with a wrapper "interpreter": https://github.com/erning/gorun https://github.com/erning/gorun So does C: https://github.com/ryanmjacobs/c https://github.com/ryanmjacobs/c So does Haskell: https://stackoverflow.com/a/8676377 https://stackoverflow.com/a/8676377 So does f#, via `#!/usr/bin/env fsharpi --exec` I think You can compile python: https://github.com/dropbox/pyston https://github.com/dropbox/pyston You can compile JS: http://enclosejs.com/ http://enclosejs.com/ I wouldn't be surprised if someone found a way to AOT-compile bash, but I'm not going to bother looking for that. The only criterion I've found which makes some sort of sense is whether the language designers consider "scripting" a use case to actively support and use to drive language features, or if it's a second-class citizen.
- fulafel 8y agoNitpick: If you are using another language that compiles to JS, I think an improved formulation would be "JS has the best feature set of the runtimes / ecosystems used for scripting". (I like ClojureScript and Elm more than TypeScript for web development, and prefer Python for non-web scripting, YMMV)
- wutbrodo 8y ago> developers that don't think specifying types is helpful are still early in their careers (those who suffered in the dungeons of Java get some slack) I'm not high-confidence about this heuristic because 1) the "class label" is a bit subjective and 2) I don't have a massive sample size, but attitudes toward typing is one of the best filters for engineer quality I've come across. (No, I haven't put this in practice in interviews, and I don't ask any related question. It's just a correlation whose strength I've found really striking) It's part of a broader class of heuristic I've been noticing recently (again, still a very preliminary, low-confidence model): things like "lack of reliable, quality devtools" and "inability to customize interfaces" bother highly-productive engineers more than less-productive ones, which is what you'd expect given that inefficient interfaces to their work has a far greater cost to the former. Along these same lines, if (eg) you're already pretty bad at understanding complex systems by reading code, you're much less likely to notice or care about how much more difficult dynamic typing makes this. I should be clear: this isn't a general-purpose argument against dynamic typing, and I'm not suggesting that the situation is as simple as "dynamic typing bad, static good". They both have their strengths and weaknesses, which make each appropriate for different situations; I ended up picking Python for a company whose tech org I was responsible for building, and as much as I personally find engineering in Python to be horribly unpleasant, it was the right choice for the company given the environment it was in, and I would make the same choice in the same situation. I don't think my theory above is particularly novel, and I understand the self-serving bias that it aligns with, which is part of why it's still such a low-confidence model. But I've been unable to wrap my head around the number of nonsensical defenses of dynamic typing I've seen over the last few years, and this model is the first to offer an explanation: if you can't tap into the benefits of static typing, of course the accessibility and flexibility of dynamic typing is going to seem like it far outweighs the foofy, theoretical benefits that static typing brings to stability and comprehensibility.
- Throwaway879989 8y ago> It's part of a broader class of heuristic I've been noticing recently (again, still a very preliminary, low-confidence model): things like "lack of reliable, quality devtools" and "inability to customize interfaces" bother highly-productive engineers more than less-productive ones, which is what you'd expect given that inefficient interfaces to their work has a far greater cost to the former. Along these same lines, if (eg) you're already pretty bad at understanding complex systems by reading code, you're much less likely to notice or care about how much more difficult dynamic typing makes this. I think for me it is the other way around actually: I believe I'm worse than the average programmer at keeping complex states in my head, thus I push heavily for high quality code and tools to reduce the times I have to fight through particularly nasty debugging / refactoring sessions .
- C1sc0cat 8y agoMy experience is that developers should really realise quickly that strictly adhering to defining all your variables is a very good thing. But with the rise of JIRA and the pressures to close tickets with the least amount of work a lot of newer developers don't realise this or are not allowed to spend the time to do it right the first time.
- deleted 8y ago[deleted]
- sametmax 8y agoI believe the most amazing feature of JS is the ability to make their devs think they got it all figured out. > Python relatively recently added typing[0] The typescript compiler and the mypy type checker both appeared in 2012. Function annotations have also been officially part of the Python syntax since 2006, although they could be used for more than typing. Browsers still do not support the typescript syntax as of today, you need a transpiler. > parallelism support (recently in v11 w/ worker threads), and built in async IO paradigms give Node a huge leg up over ruby, python, and perl. Python has supported non blocking processing as far as 21 years ago with threads. It's actually the language of choice for pentesting a networks because it's so easy to implement a custom service scan. Python then, in 2002, saw the rise of Twisted for pure asynchronous I/O + callbacks, as it was for JS and AJAX at the time. Ansyncio came way later, yet Python implemented async/await and yield before it was part of JS. Python implemented multiprocessing as well, which allows to leverage multiple cores, more than 10 years ago. I remember that producing the equivalent result ishard to use accross all major browsers, and nodejs, consistently. The Python multiprocessing pool has even not changed API when we migrated from Python 2 to 3 and works with both (I just tried it to be sure). > Weirdly enough, JS is the best in my opinion precisely because it does so much to not be itself. I think you should try to put in production 4 or 5 other languages before stating such a strong opinion. Your post feels more like over enthousiasm due to lack of experience than a real analysis of the state of dynamic programming languages. There are strong qualities to Perl, PHP, Python and Ruby. The fact they are so popular without having an accidental absolute monopoly on the most extraordinary plateform of the world (the Web) should at least give you a hint of that.
- hardwaresofton 8y ago> The typescript compiler and the mypy type checker both appeared in 2012. > Function annotations have also been officially part of the Python syntax since 2006, although they could be used for more than typing. > Browsers still do not support the typescript syntax as of today, you need a transpiler. I did not make a statement about the typescript compiler/transpiler nor mypy, I made a statement about the typing module which was brought about by PEP 484 (proposed in 2014) and accepted in 2015 a full 3 years after the typescript compiler came on the scene. JS got gradual typing first, even if it was through transpilation -- there are even earlier examples of syntax enhancement (though it was mostly sugar) with coffee script from even earlier. JS is undeniably more innovative in this aspect -- it's also made more mistakes as well. It doesn't matter what browsers support, because the code is transpiled. The point is that you have access to better tools as a developer while writing code. Is your point that python have been specifying their types in their code in any sort of numbers since mypy was invented? Because I sure don't see that on slides PyCons over the last ~5 years. > Python has supported non blocking processing as far as 21 years ago with threads. It's actually the language of choice for pentesting a networks because it's so easy to implement a custom service scan. > Python then, in 2002, saw the rise of Twisted for pure asynchronous I/O + callbacks, as it was for JS and AJAX at the time. Ansyncio came way later, yet Python implemented async/await and yield before it was part of JS. There's a difference between what's possible and what's easy/facilitated well by the standard library of a language. I did not imply that python could not do non-blocking processing. My point was that these patterns were not easy and were not standard -- and the community floundered for years between alternate solutions (gevent/twisted/tornado), eventually creating asyncio while NodeJS has had support for this feature built in from the start. Also I'm not sure that pentesting stat is correct -- ruby is extremely popular and so is/was perl. Scripting languages with decent standard libraries and easy semantics are popular, not necessarily non-blocking processing support. > Python implemented multiprocessing as well, which allows to leverage multiple cores, more than 10 years ago. I believe producing the equivalent result is still hard to use accross all major browsers, and nodejs, consistently. The Python multiprocessing pool has even not changed API when we migrated from Python 2 to 3 and works with both (I just tried it). Please see the other comments. No one is saying multi processing is impossible in python, I specifically called out that it's done by starting other processes. There are subtle differences between how node worker threads and multi-process setups work, in particular the shared memory space and communication mechanisms. The GIL is also an issue. > I think you should try to put in production 4 or 5 other languages before stating such a strong opinion. Your post feels more like over enthousiasm due to lack of experience than a real analysis of the state of dynamic programming languages. > There are strong qualities to Perl, PHP, Python and Ruby. The fact they are so popular without having an accidental absolute monopoly on the most extraordinary plateform of the world (the Web) should at least give you a hint of that. So your point is that everything is different and everything has it's own benefits? Well that's impossible to refute so I'm just going to restate my point, maybe you can try and refute it directly. Javascript has the accessible (and thus widely adopted) and easy to use implementation of the following features, today in 2019: - Rigorous and powerful compile time type checking - Parallel computation (without spawning another process or the effects of a GIL) - Asynchronous IO The combination of these three features being accessible is what makes Node stand out in front of Perl, PHP, Python, and Ruby. Python may have "had" the capability to do the things above at various times in the past, but it's technically been capable of doing just about anything, like any other programming language -- you can launch sub-processes from bash, doesn't mean you should use it for large applications. What makes a good language is accessible and easy to use features that make you both correct and productive. Node has more of these tools available, and they're more accessible in Node than they are in Python, and more people are using them. Typescript offers more robust type support than typing+mypy. Node worker threads, though very recent, provide parallel computation without child subprocesses, in a shared memory context with no GIL. Asynchronous IO is second nature to JS developers, while that's definitely not the case for python developers. [0]: https://www.python.org/dev/peps/pep-0484/ https://www.python.org/dev/peps/pep-0484/
- ceronman 8y ago> "extensive" unit testing is a poor man's type checker Wow! No! If this is what you feel, you might have been doing unit testing wrong the whole time! Unit testing is a powerful technique that is useful regardless of your language. the first unit testing libraries and frameworks started with Statically Typed languages.
- boomlinde 8y agoI don't think that the point is that unit testing is a poor man's type checker in general, but that "extensive" unit testing in a dynamic language may include a lot of testing that could have been weeded out by automatic analysis based on a static type system.
- hardwaresofton 8y agoJust chiming in to say you're correct -- that's exactly what I meant. For example, if you write a function that only makes sense on numbers greater than zero, then make it take a `GreaterThanZero<Int>`. It's a contrived example but people often pride themselves on writing unit tests that check for "out of bounds" cases like that, and defensive coding in dynamic languages usually starts with "make sure they gave you the right things and nothing is null". There are cracks to slip through with Typescript (it's not as good as using a language that enforces this stuff down to the runtime -- i.e. haskell), but in general you're going to avoid these kinds of errors in the first place if you write sufficiently useful types. Another hot take: The value of different types of testing is as follows (most valuable first): - E2E tests that test customer flows - E2E tests that prevent regressions (made after a bug was discovered) - Smoke tests - Integration tests - Unit tests
- ceronman 8y ago> - developers that don't think specifying types is helpful are still early in their careers (those who suffered in the dungeons of Java get some slack) Developers who believe specifying types doesn't have any drawbacks are still early in their careers :D
- untog 8y agoTypeScript is a great middle ground in that regard. Doing something that is made tricky by types? Just cast it to "any" and do whatever you want.
- drugme 8y agoPython relatively recently added typing[0] Python always had "types" of course. What Python 3 added was type hints (an approximation of static typing, if you will).