CIL (.NET bytecode) to WebAssembly compiler
github.com
github.com
> No transpilation
You'll have to compile instead.
> people will be able to get rid of javascript wholesale
Modern JS (ES6+) isn't worse than Java or C# in terms of expressiveness. In fact, it might even be better in some cases.
No other language is going to come with built-in tools for editing within browser/client dev tools. Modern JS is going to be one of the easy languages to get started on.
And of course, you totally underestimate the billions of lines of JS already written for the Web.
ES6 isn't statically typed. It might be better for you , it is not for me.
> You'll have to compile instead.
Yes, and without caring about Javascript. That's the point. Javascript will become irrelevant when it comes to front-end development. One language cannot possibly satisfy everybody's needs.
If that was the case we would all be using nodejs on the server and that's hardly the case.
Perhaps you should just look into using TypeScript? It's basically ES6 with static typing.
> Javascript will become irrelevant when it comes to front-end development.
I understand the enthusiasm but this becomes a bit of an argumentum ad populum.
So you are saying that because it isn't statically typed it's inherently worse in terms of expressiveness?
There's a valid argument that static typing has big advantages (navigation, refactoring) but it worries me when people write off dynamic code entirely.
That being said, yes, it has been shown that, for large projects, statically typed languages are strictly superior than dynamically typed ones.
[1] ES6 isn't statically typed. It might be better for you , it is not for me.
Don't get me wrong here, I like a LOT about C# but expressiveness compared to JS doesn't even come close, when you include the pending ES7 stuff via Babel.
I think people forget that, in JS, the types still exist. Just because it's not statically typed doesn't mean you don't have to think about types and what types are appropriate for given scenarios.
With JS, it's impossible to tell just from inspecting a reference to a function what it expects from you and what you can expect to give back. You have the length property to tell you the number of arguments and that's it. Of course, that's assuming it's not using a variadric arguments pattern, in which case the length value only tells you the minimum number of parameters expected, but not that more are possible.
Even if you can make reasonable assumption about the number of parameters, you won't be able to tell at all what types the function expects for those parameters. Want to list all the functions in a class that take two numbers and return a different number? Can't do it.
But still, if you could make reasonable assumptions about the type of things that go in and out of the function, you won't know how to even call the function. Does the function expect to be called as a method of a class? Does it expect to be called as a static function? The best you can hope for is to toString the function and check if the source includes the word "this". Here's hoping it's one written in JS itself and not one that is implemented internally in the browser.
Now before anyone says "why would you ever need anything like that?", it's an absolute necessity for building any sort of user-driven or data-driven reporting system. You need to be able to tell when your data set matches the functions you want to apply to them, at run-time, because the data isn't available at design-time. It's the classic reflection use case.
As far as I'm concerned, safety-guaranteed reflection is impossible in JS, unless you throw away JS functions almost completely and create your own Functor class with all the extra type information that you would need.
For that matter, you can use an object stream, and pipe it all through to resolution. If your data comes from variant sources (spreadsheets, dirty xml, etc) then you are way better off with a scripted language.
Try importing a WSDL that defines various interfaces to use "Object" and VS/.Net chokes on it.
As far as users go, without the hard enforcements you can coerce values into either what you expect or cleanly drop out... unlike .Net where you have to go through the Try versions of convert, on who knows how many types in order to get something resembling predictable values... that doesn't even include regular expression syntax as a first class concept in JS.
I've handled dynamic input sources from both .Net (VB.Net and C#) and I'll tell you that most of the time JS/Node is simply easier... I've replaced complex importers written in .Net with straight forward, easy to reason with JS importers that run in Node, and edit/run/deploy without a compile step.
I will say that I do like that VB.Net has XML literals which can be very useful... but now that JSON is getting to be more common JS is less of a disconnect.
The things you're talking about doing, they are bad software design.
JS doesn't even come close to the expressiveness that you get in C# due to the fact that in JS, you don't even know the type of arguments being passed in any given function without looking elsewhere in the code - therefore, it's not easy to understand.
If you're going to go with the definition that says expressiveness means "the variety and quantity of ideas that can be expressed", Javascript also loses there since there are whole classes of behavior that cannot be practically expressed in Javascript. For instance - try writing a function that only accepts a standard single precision floating-point number as it's argument and see how much work you have to do compared to other languages.
Try expressing a Dictionary, Linked List, HashTable, SortedList, SortedDictionary, etc in JS - you'll be writing those structures yourself or cobbling together some random lib. Better languages let you actually express those things without having to write them yourself.
ES "let's you work around this" in that it let's you just do stupid shit until it blows up in your face. Statically typed languages force you to consider those scenarios that might lead to blow ups. You still have to consider those scenarios in ES, but the language doesn't force you to, so you have to have the diligence to do it yourself.
"Expressiveness" doesn't mean "write as little code as possible to get the base case running". Expressiveness means the ability to implement different patterns of solutions with native syntax. C++ is "more expressive" than C when it comes to object oriented programming, not because C cannot do OO, but because C++ has specific, checked syntax for it.
References are consistent and one-way, you no longer have to deal with searching for where a given dependency is coming from... Or where the implementation is... references are always direct this way.
C#: using MyOrg.Base.Interfaces;
public class Foo {
public IBar Bar {get;set;}
public string Baz() {
//wth is IBar.Baz implementation come from?
//damn, now I need to search the project for IBar
return this.Bar.Baz(this);
}
}
JS import bar from '../lib/bar';
export default function baz(context) {
return bar.baz(context);
}
In the JS case, you know where the implementation of bar comes from when looking into code, trying to resolve a bug. You can also use proxyquire in order to test the module, replacing bar with a shim for the purposes of testing... in the JS case the code is still clean, and you don't have a couple of layers of indirection abstracting you away from finding the next piece in the puzzle. And it doesn't limit your ability to test.And I don't know what that last part is supposed to mean. I've never not know "where my dependencies are coming from" or "where the implementation is". It's not like they live in some hidden place that I can't access. I reference them directly and explicitly.
EDIT: you ninja-edited on me. No, you are not at a loss for where IBar is defined. It's extremely easy--a single key press--to find it. Just hit F12 on it. You'll go right to its definition.
I'm not saying these patterns should never be used... only that there are generally simpler expressions that should usually be favored.
Here are some examples from this week:
Checking whether a passed argument is an array or a dict:
var a = []
if (Object.prototype.toString.call(a) !== '[object Array]') ...
(perhaps not js itself, but how it is used) Leaking DOM nodes are a thing:
https://developer.chrome.com/devtools/docs/heap-profiling-do...Easy things like getting values of a dictionary:
var d = {
a: [1,2,3,],
b:[4,5]
}
var values = Object.keys(d).map(function(key){
return d[key];
});in Python, it's just .values()
Errors aren't thrown when there are obvious issues with the code.
String.replace replaces one instance instead of all instances in a string.
Functions arguments are a bit of a mess.
differences between
for each (var myVar in myObject)
for (var myVar in myObject)
random things like these:http://stackoverflow.com/questions/2568966/how-do-i-pass-the...
All the things here:
http://www.toptal.com/javascript/10-most-common-javascript-m...
If you import a library, they could have modified the global scope. This is common in JS libraries. Then some things you wrote don't work.
undefined/null thing
differences between var declared function and regular named function.
Many things in the language are not obvious and you have to discover them through trial and error or study JS internals and find out how things are implemented.
Luckily solved in ES2015:
Array.isArray(thing)
The toString trick is pretty outdated, in ES5 you can also do:
thing instanceof Array
> (perhaps not js itself, but how it is used) Leaking DOM nodes are a thing
Definitely not JS itself, it's easy to create circular references between JS objects and DOM elements. It's just the way the DOM is (poorly) designed and the way it interacts with JS.
> for each (var myVar in myObject)
That's not even standard, just a Mozilla "dialect". I don't think that's supported by any engines other than SpiderMonkey and predecessors.
> thing instanceof Array
instanceof is ES3.
> That's not even standard, just a Mozilla "dialect". I don't think that's supported by any engines other than SpiderMonkey and predecessors.
To quote MDC:
> The for each...in statement is deprecated as the part of ECMA-357 (E4X) standard. E4X support has been removed, but for each...in will not be disabled and removed because of backward compatibility considerations. Consider using for...of instead. (Please refer to bug 791343.)
for each (var x in a) ... <<Firefox only??>>
for (var x of a) ... <<ES6>>
for (var x in a) ...
a.forEach(callback[, thisArg])
Knowing JS, each of them have their own quirks probably.for each (...) -> It's not supported anywhere, so forget it.
for (var x in a) -> x is the key, so it's kind of inconvenient. You have to watch out for inherited properties/methods so one should check for a.hasOwnProperty(x).
for (var x of a) -> It has mostly no gotchas. Only poor browser support.
.forEach only works with arrays and from ES5 on. You have the good old "this"/scope gotcha.
if (a instanceof Array) ...
// or polyfill
Array.isArray = Array.isArray || function(a) {
return a instanceof Array;
};
Object.keys can be cleanly shimmed without braking older browsers. You can always shim in the behavior you want, as long as you don't need IE7 support. Object.prototype.values = function() {
var instance = this;
return Object.keys(this).map(function(key){
return instance[key];
});
}
Replacing globally in a string console.log("I lose and lose again, not even close.".replace(/\blose\b/g, "win"));
If you're using ES6 or node-style modules, you shouldn't generally mess with global state, unless you are polyfilling new features. Promises (bluebird), fetch, etc...Understanding falsy values is a core part of learning JS, as is coercion... no it isn't perfect, but there are flaws in any language you can bring up.
As to a function assigned to a variable vs a function declaration, well again that's part of learning the language.... Being able to use functions as first class expressions is a very powerful feature, that frankly works pretty well.
Of the features missing from JS proper, an isolated invokable web-workers scenario with plain, side effect free functions/modules would be a great start (not the current way via secondary script).
That said, most of your complaints are things that are easier to work around, or simply things that you learn with the language. It's not that different from learning warts in Python (which is better than many), C#, Java or anything else.
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[window.frames.length-1].Array;
var a = new xArray(1,2,3);
>> a instanceof Array;
<< false
>> a
<< Array [ 1, 2, 3 ]
>> Object.prototype.toString.call(a) === "[object Array]"
<< true
All I'm saying is there are way too many such things that you have to keep in mind.Most likely when working across frames, you should use messaging, unless you're doing something truly hokey... In either case, working across frames like that is akin to poking into the memory of one process from another. It's bound to have issues...
I don't think this is something that WebAssembly would allow you to do in the first place...
Things that take 5 lines in JS take 200 in C++ all to make the type system happy. Yes I understand the trade offs. Wrote games most of my career. I used to find it cool that I could write a 400 line templated intrusive list class that generates just 1 instruction on use. Yippee. Now though I just resent the fact that have to write giant implementations like that for code who's performance doesn't matter.
In JS forgot a little piece of data? It's generally almost zero lines to hack it in. C++? It's often refactoring hundreds of lines of code.
Wanna to wrap some function to monitor it, test, sanitize, .. trivial in JS. Next to impossible without massive refactoring in C++
When I have to do C++ again I will but it won't be without kicking and screaming.
import { isArrayLike, values } from 'ramda';
const a = [];
const aIsArray = isArrayLike(a);
const d = {
a: [1,2,3,],
b:[4,5]
};
const dValues = values(d);
Not to mention that a lot of the problems you mention have native solutions in ES6.JavaScript is a very different language than the one people used to use 5 years back.
Why should people use JS with a non-standard library when dictionaries come built into better languages?
I do not agree that everything should be handled with standard libraries. It's better for these things to be modular and versioned, instead of them being pulled from a big bloated standard library.
The code clearly does what was being asked in a very simple and non-broken way.
Perhaps the issue here is that non-JavaScript engineers are used to kitchensink standard libraries and avoid mixing and matching to get the best experience the ecosystem offers.
The problem with mixing and matching libs is that no two JS devs do it the same. Some will even re-build the same lib that has already been built by hundreds of JS devs because NIH.
In your universe, engineers do not talk and accidentally decide to use two libraries that do the same thing within a project.
I work with JavaScript and I rarely see this happening.
It's hard to compare. Java is horribly verbose, but C# (and F# even more) is pretty concise these days, definitely comparable to JS if you factor in the increased lines of code you need in a dynamic language to have any certainty when refactoring.
Good and 80% of JS bugs will disappear in a puff of smoke ;-)
I think most coders would choose a language that has better tooling and robust standard library over Javascript which doesn't even have a standard library. This is certainly the death of JS.
I think you've confused the present with the future. No other language comes with that today. There's no reason other languages shouldn't in the future, however.
https://github.com/WebAssembly/design/blob/master/TextFormat...
Says who? I don't think it's going anywhere.
I for one will be happily programming in ES2015+ in the future, for many years to come. And I know I'm not the only one (have you ever been at a JS conference?).
Anyways WebAssembly is very much welcome. I can't wait to use python or haskell "natively" in the broweser.
If someone build a great tool, lest's say the equivalent of D3.js, in Java; I don't see a way I can use it in python without having to write a python API for that library.
It's not necessarily bad. The first advantage being, that hopefully people are going to stop recreating new javascript frameworks every 2 months.
https://github.com/WebAssembly/design/blob/master/FAQ.md#is-...
But It would be real nice to use C# as wasm.
It really takes something like WebAssembly which multiple browser vendors back to get traction... Adobe was in the position to give us this almost a decade ago.
Is there a runtime environment for executing wasm available yet?
http://blogs.msdn.com/b/webdev/archive/2015/09/02/announcing...
I've totally missed them in modern JS development, and haven't been fighting against many of these practices for years now at all (/sarcasm).
Seriously though, my biggest issue with JS development today is people that don't understand patterns beyond what they use in C# and Java, and don't want to keep things simple and easy to reason about. Most C# and Java applications I've worked with have many layers of unnecessary complexity for the sake of, more because "that's how it's done in 'Enterprise' software" more than it is about what's truly needed.
I actually really like C#, and the thought of being able to use some of the features really appeals to me. That said, actually working with solutions common from .Net, I've been happier without it. I've spent the better part of my time the past 4-5 years migrating away from .Net solutions to Node based ones... once you get past people trying to implement overly complex patterns and embracing "the node way" of simple, composable, functional modules... it can and does go much more smoothly.
--- edit:
When I say complexity for the sake of... it's usually for the purpose of testability, often in scenarios that don't have tests, and beyond that aren't trying to target multiple implementations of an interface. Even then, with JS you don't need the added constraints. I know there are "contract" concerns, but what that gets you is WS-* and SOAP/WSDL hell that nobody really understands vs easy to reason REST/JSON services. In the end, having simple systems where you have to learn a bit of convention tends to be easier than complex systems with layers of indirection.
As programmers on the computer all day, the more work the computer does for us the better. With a type system the computer knows what the system is capable of, and so knows what you are doing - this means it can tell us precisely what members are available in 'foo' when you type 'foo.', and it can accurately tell us that 'bar' does not exist in foo when you type 'foo.bar'.
With systems of even minor complexity this is a godsend when you don't have to even read the documentation of a new API you want to use - you just use the autocomplete and contextual documentation to figure things out. It makes code fun again.
With dynamic typing, and especially with JS, the computer is mostly oblivious to what can/cannot be done and you end up having to ctrl+F on method names, mispell something and it just gets added as another variable to the type, you can't refactor variable names easily etc. It's pretty bad in comparison.
Static typing isn't all perfect though - sometimes types do get in the way where I wish more dynamic features would have been available. But at least now if C# etc can be used for webdev, then solving these problems will become something people will invest time in and we will finally see new innovation again - instead of yet-another-javascript library/hack.
Compilers are great, they exist for a reason. Use them
EDIT: A: No, you can't.
I hope WASM gains some sort of GC eventually, because writing a GC in WASM will make me cry. :-(
You can still strongly type everything within your project but creating a complete strongly typed wrapper to the web api would be a big job.
https://groups.google.com/forum/#!topic/google-web-toolkit-c...
My thoughts are pretty much exactly what Colin said.
Without GC it's not a reasonable target for Java cross compilation because you'd have to embed your own GC implementation into the output.
That being said, they plan to add GC, which will make it more attractive.
Indeed, we invited vmorgulis to repost this one, which we sometimes do when a good submission didn't get much attention the first time. I've written about this at https://news.ycombinator.com/item?id=9866140 and https://news.ycombinator.com/item?id=8790134 if you're interested.