If we could push JavaScript performance to be another order of magnitude faster it wouldn't be necessary to use other languages, imho. Of course, pushing it that far without effectively creating a new one would be difficult, to say the least.
If we could push JavaScript performance to be another order of magnitude faster it wouldn't be necessary to use other languages, imho. Of course, pushing it that far without effectively creating a new one would be difficult, to say the least.
By comparison, JavaScript (and by extension, TypeScript) is still lacking fundamental features and the library ecosystem situation is pretty bad.
I wish there was a modern language that took all the good non-manual-memory-management things from Rust and added a GC and some immutable data structures. Error handling, enums, macros (with compile_error! / diagnostics API), traits / approach to OOP, embedded tests, doctests and the relentless determination to add examples in the docs in general... Everything in Rust feels like "oh, they got this right too", which hasn't been the case for any other typed lanuage I've used in the past 15 years (including typescript, my previous favorite; purescript; go; haskell)
I ask because I have never delved into C# only heard it's Microsoft's Java. And I am no fan of the original Java at all so C# gives me pause.
Speaking as someone who started with Java 1.2 and saw all the crap that happened to it.
C# is currently lightyears ahead of Java in every way, especially now that MS is not Micro$oft to people on the internet any more =)
Let’s not claim things that can’t be objectively proven. C# does have much more features than Java, but that is not necessarily a plus in case of a programming language. There are features that are definitely better, but I am not bought that the whole would be.
Plus, ecosystem-wise Java is much bigger and much more open-source. The runtime is also better on the JVM-side, though this is offset by C# expressing more low level details.
I've been doing C# on a MacBook with JetBrains Rider for years. Some code runs in Linux containers, some on AWS Lambda.
I rather do .NET than Java, but the FOSS story isn't as Microsoft sells it, hence why on our agency .NET is mostly used on Windows projects, and usually loses against Java or node in UNIX like RFP, even after .NET Core reboot, because of dependencies and existing enterprise tooling.
DI is almost always in web, but via constructor instead of annotations.
Similarly recent libraries such ASP.NET have been working hard to use more of these things to eliminate their own boilerplate. The latest ASP.NET templates use top-level statements and some global usings and are getting very lightweight in terms of starter-level code.
.NET does have annotations and dependency inversion, but those too tend to avoid boilerplate more than create it. Few annotations are "required", depending on your domain and which libraries you are expecting to use. .NET now has a single, mostly standardized dependency injector that almost everyone has agreed to use (Microsoft.Extensions.DependencyInjection) at this point. It intentionally only supports a bare minimum of Dependency Injection needs and is nothing like the Kitchen Sink approach of something like Java's Spring. (For instance, zero out of the box support for wiring Dependency Injection via XML files. .NET's DI is always code driven, often in a Startup.cs, Program.cs, App.cs, or Main.cs file.)
I've been increasingly finding in C# that I'm writing new code with zero templates and almost no snippets-expansion. (There will always be plenty of legacy code out there with much more verbosity, of course.)
The easiest suggestion is to try it for yourself. The `dotnet` tool is cross-platform, generally an easy install, and its `dotnet new` command will help you try many easy template types. You can relatively easily work entirely in VS Code today (as opposed to older versions of C# often "needed" the full bulky Visual Studio install for templates, language servers, and other stuff).
I do hope to try it maybe in recent future.
They had me at features, lost me at manual compilation ordering.
C# can fake algebraic data types in some ways/some cases. Though if you are expecting to do a lot of it you are still better off in F# or C#/F# hybrid projects. (F# of course being a proper ML-family language.)
Or in Scala, technically not an ML, but is as close as you'll get in a nominally typed language.
enum RGB:
case Red, Green, Blue
def log(x: RGB) = x match
case Red => print("red")
case Green => print("green")
// error, not exhaustive
Obviously Scala can do a lot more, including GADTs, which Rust will never have until HKTs are supported.Ton of powerful languages to choose from these days, good times...
It's my general purpose language. I also use Rust everywhere Kotlin isn't suitable.
Swift seems more in the Go or Java class, rather than being competitive with C/C++ like Rust is. If that's so, Swift is still appealing as a pretty-fast, safe language with a much more sophisticated type system than Go or Java. But... TypeScript is too!
I have a feeling in terms of raw performance, JS is probably closer to Swift than Swift is to Rust. The important difference between Swift and JS isn't performance as much as which platforms/APIs/languages they can integrate with.
(Maybe I'm underestimating Swift's performance, though, or overestimating JS -- corrections welcome)
I feel like the entire industry has had a "kneejerk reaction" to C++ and its abysmally slow compile times. Everyone jumped onto the interpreter bandwagon and ended up throwing the baby out with the bathwater.
It is definitely possible to have sub-second compile times for large, complex software! Just look at Jonathan Blow's Jai language. He can recompile and reload an entire 3D game engine in about that time.
We can have our cake and eat it to. We can have efficient, compiled languages and still have safety and fast compilation.
I can only think of Ruby and Python that use a strictly interpreter mode (in their most common runtime).
Java, C# use a hybrid solution, but for all practical purposes they are running as extremely efficient machine code, how is it not “efficient business language”?
But sure, though I don’t really buy the argument that JIT compilers would “severely limit” the type of optimizations - there is no significant performance difference - if any - between AOT compiled managed languages and JIT-compiled ones. Sure, there are more constraints in case of a JIT, but it’s not like going in the other direction and letting gcc/clang chew 10x time more on the same program would give you a significant speedup, if any. Speculations (which are not possible AOT) may even reverse the fields.
D, Haskell, OCaml, Go are all in the same ballpark as Java and C#, and even JS, hell, they may be better.
Imagine a language as easy to use as Python, with the strong typing of Typescript, but designed from the ground up to always be fully compiled and hence running as fast as C++, but with build times measured in fractions of a second... fast enough to feel interpreted.
This extra optimization is somewhat offset by the very point of a managed language: the programmer don’t want memory layout details to leak into the design/APIs, but in the rare case it is needed it can be done just as well with the escape hatches they provide (byte buffers, value types also bring you quite far). But business logic seldom involve these scorching hot loops to begin with, so there may not even be anything to optimize in this manner.
Or as others have said, F#, or maybe Scala. Or if you're feeling really brainy, Haskell.
But Rust was, in its early days, basically inspired by the ML type system, its type inference model, and its pattern matching facilities. The first Rust compiler was written in OCaml.
This basically describes all of the recent ML – perhaps more specifically OCaml – influenced languages like Kotlin, Swift, F#. (Rust is also heavily influenced by OCaml but its distinguishing feature is manual memory management with lifetimes.)
I do wish we had a good Linux/Posix option with as good of a package manager as Rust's cargo. Kotlin and Swift have some support but are largely focussed on the JVM and MacOS respectively. OCaml itself is of course an option here but its syntax and smaller ecosystem is a stumbling block. Reason is an attempt at a more familiar syntax for OCaml but that community is mostly focussed on transpilation to JavaScript with ReScript.
Here is another more subtle but important example: flexible API for error conversion, powerful language features and macros together enable the language, in conjunction with libraries like https://docs.rs/anyhow/latest/anyhow/ which gets you the best of all worlds in error handling: concise `?` operator for writing error handling code, eas to add additional message context (using `with_context` from anyhohw), differentiating between functions that can and cannot throw in the types (Result<T>), and the ability to get exception style backtraces from Result, too (that last one seems to be rare)
Another subtle QoL which is often overlooked when implementing macros: `compile_error!` (and soon even more powerful diagnostic API). With that, macros can report custom errors back to the programmer via the compiler and language service, rather than becoming an incomprehensible mess. For example, the peg parser macro will mark errors with infinite left-recursive rules that don't have caching set up with custom error messages.
The big problem is the gap between TS and JS. User defined typeguards are a usable work around but it would be nice to be able to use a native isMyType function.
Also would be nice to have constraints natively in types. Like string lengths or max ints.
Arguably the highest quality TS lib out there.
Being able to generate types, encoders, decoders, apis, guards and even arbitrary data is extremely powerful.
I feel like the name could use a bit of work for a start! "schema" is way too generic.
Want structural/duck typing? No problem; that's the default. Define new interfaces that old classes happen to implement without having to wrap them. I always wanted that feature!
Want nominal types? No problem; just declare a field indicating the type name!
interface Square { classRef: "http://example.com/Shapes/Square"; width: number; }
interface Circle { classRef: "http://example.com/Shapes/Circle"; diameter: number; }
type Shape = Circle|Square;
(I like to express things in a way that can be easily translated to RDF, hence my use of URIs for type and attribute names)Since TypeScript types don't runtime checks, you can even do it on atomic types!
type USDollars = number & { [Symbol.for("http://ns.nuke24.net/Synx/unit")]: "USD" }
type CanadianDollars = number & { [Symbol.for("http://ns.nuke24.net/Synx/unit")]: "CAD" }
const someAmount : CanadianDollars = someExpressionReturningUsDollars; // Compile error! Try doing that in Java! I OFTEN WISH I COULDA pile of thoughts on the subject from back when I first came up with it: http://www.nuke24.net/plog/32.html
- for functional programmers TS offers lots of flexibility and power many other languages including statically typed and pure don't
- TS functions or methods that throw don't show up in the type system (they do in Java)
I hope TS keeps getting stricter.
Typescript types don't exist at run time, at all. So it's easy to be better when your language is merely about static analysis as it will not enforce any sort of type system during runtime. Java, Go or C++ have different constraints.
There are no types whatsoever as far as processors are concerned. No types in assembly Not for Go or Java, not for C, and not for Rust. All you gotta do is keep compiling.
I disagree, Javascript does have types and runtime type errors, just not all the ones Typescript compiler has, it makes Typescript extremely leaky as a Javascript abstraction. Typescript compiler cannot represent every single Javascript type combination either, it will would have to be a Javascript interpreter at first place.
Here's types existing at runtime: https://go.dev/play/p/rc--yVzJ9bt
And it would speed up the TypeScript Compiler.
My bet is:
TypeScript typechecker in Rust:
It's simply impossible to keep up with TS for competing compilers.
The type system is really nice, so even without being able to use the full range of JS hacks and escape hatches, I think it’d still be a nice language to work in.
Example: https://www.typescriptlang.org/play?#code/MYewdgzgLgBAtgTwLI...
In the example above, the problem is that typescript allows casting function types to omit optional arguments, and also allows using a function with n arguments as a value where a function with >n arguments is expected
Nothing is abandoned and in any case typically only a small set of libraries is needed which should be carefully picked.
Node.js: https://nodejs.org/api/worker_threads.html
Browser: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers...
However, threads are very rarely needed. The common use case in other languages is I/O, and JS environments handle that with async I/O—a superior choice, IMO.
And the language and the VM has been, and will be for any foreseeable future, single-threaded.
Whatever it supports, Javascript-the-language has no concept of threads. And workers are basically external processes with a somewhat awkward event-based communication and certain limitations.
Whatever Deno uses internally to implement them has no bearing.