AtScript Primer
docs.google.com
docs.google.com
There is no reason that a similar project could not have been made via smaller modules using comment annotations.
This project really should be at least two projets: (1) one npm module for parsing the type signatures with the line numbers of the functions it applies to. (2) one module that takes in that intermediary representation and performs the AST transform for wrapping the functions.
I don't see why this couldn't have been accomplished with:
(1) the doctrine module [0] for parsing JSDoc comment blocks before functions
OR a custom module for recognizing a custom comment delimiter like //+ or
//! followed by the type annotation such as Haskell's type declaration
format.
(2) a module for parsing closure compiler JSDoc type signatures
(3) the racket-style higher order contracts module [1] for a way to do
run-time checking
(3) a module consisting of all the possible permutations of higher order
type checking functions based on rho-contracts
(4) the node-falafel module [2] for performing the actual AST transform
that wraps those contract functions around the function described by
the JSdoc comment.
Furthermore, this approach of breaking this up in to modules allows multiple people to propose alternative syntaxes for this for consideration in future versions of ECMAScript. I wouldn't be surprised if sweet.js could also be used for those
syntax approaches that go beyond comment-based annotations and involve modifying the syntax of the language itself.For those that built this at Google, please please please consider breaking this down into smaller composable modules. I'd love to be able to play with the subcomponents of this myself without having to adopt yet another language that doesn't parse with off the shelf tools [4].
[0] https://github.com/Constellation/doctrine
[1] https://github.com/sefaira/rho-contracts.js
[2] https://github.com/substack/node-falafel
[4] See JSX for the clusterfuck[6] that results when you add yet another format that needs to be parsed in a unique way with no real benefit that couldn't be accomplished just as easily without fucking with the standard language syntax. See Wadler's Law [5]
Type annotations are a strict subset of the "this" that AtScript seeks to accomplish.
> Do we really need another compile to JavaScript language for something that did not require changing the language syntax?
"Need" is a fuzzy term, but I think it clearly benefits from a new language with new syntax fitted for the semantics rather than trying to hide new functionality in a separate sublanguaged inside JS comments as you suggest.
> There is no reason that a similar project could not have been made via smaller modules using comment annotations.
There's no reason it couldn't be done, although there are reasons not to prefer it (noted above), and in any case preprocessing comment annotations in what is otherwise JS to generate additional JS code for runtime type checking is creating a new compile-to-JS language, its just putting the code for that new language in something that looks like JS comments, so it would still be doing exactly the thing you say shouldn't be done (or, in other words, your suggested alternative suggests that we must really need another compile to JS language to do this, since your alternative still creates such a language.)
like?
> "Need" is a fuzzy term, but I think it clearly benefits from a new language with new syntax fitted for the semantics rather than trying to hide new functionality in a separate sublanguaged inside JS comments as you suggest.
When I used "need" I was suggesting that the syntax proposed did not have to be a mandatory part of adopting this feature. If you break this isn't smaller single purpose modules, you leave people the option of choosing your special syntax or choosing to build upon most of your work to make something that doesn't break all your existing tooling. Clojurescript and PureScript are example of a compile-to-javascript languages that needed another format. In the case of clojurescript, only another syntax will afford you the power of S-expressions. My objection with AtScript is that the new syntax could have been a completely optional interface for getting the benefits of the tooling actually doing the heavy lifting in this module.
> in any case preprocessing comment annotations in what is otherwise JS to generate additional JS code for runtime type checking is creating a new compile-to-JS language, its just putting the code for that new language in something that looks like JS comments, so it would still be doing exactly the thing you say shouldn't be done (or, in other words, your suggested alternative suggests that we must really need another compile to JS language to do this, since your alternative still creates such a language.)
Not exactly. Using comments allows my code to remain as vanilla JavaScript and therefore continues to work with all other off the shelf tooling out there. Asking me to adopt an entire new code format for what could have worked just fine as an extension of the standard format out there (i.e. vanilla javascript) is onerous and unnecessary. Requiring a new format requires me to through out my linters (eslint, jshint, jscs) and my parsers (esprima, acorn) and any tooling built on those parsers (ternjs, node-falafel, escodegen, browserify, sourcegraph, source maps tooling)
And...its not. The two identified components that exist now are the Traceur transpiler which generates JS from AtScript and the RTTS (runtime type system) library which works on the resulting JS. While clearly the principal intended usage model is using both together, you can use RTTS with JS without using Traceur to generate the JS from AtScript.
Basically provide a library that contains all the possible primitive types that can be checked and functions for composing higher order types.
Then in the code do something like so:
var types = require('types');
function foo(bar, baz) {
var qux = '';
/* do something */
return qux;
}
foo.types = {
args: [types.Array, types.Object],
return: [ types.String ] // array to support ES6 destructuring assignment
}
This interface makes it trivially easy to define the types, parse the types, strip the types out on minification, etc.This approach also makes it trivially easy to compose higher order types in a separate modules and require them.
my-geometry-types.js:
var types = require('types');
var point = [types.Float, types.Float];
module.exports.point = point;
module.exports.rectangle = [point, point];
Then in another file, you can require these type modules and use them to set the type signature of a function;Anyways, my point is that building a tool like this is awesome, but a null contribution if it requires me to throw out all my existing tooling, especially for something that could have been implemented in a way that is composable. It may even be a net negative contribution if it gets traction and causes an unnecessary schism (e.g. JSX) in the community that reduces code sharing, interop and the ability for developers to stand on each others shoulders.
The beauty and strength of the NodeJS ecosystem is not the language it is based on (JavaScript) or its runtime (v8/libuv), but that it nailed a lot of details related to common conventions among developers and allowing modules to remain small and composable.
The modules created by people like prominent module contributors like Substack, Raynos, Izs and Dominic Tarr are usually stellar examples of publishing small, reusable module components. All of these guys have hundreds of small modules published that are very composable, easy test and easy/fast to replace if they don't meet your needs.
The tooling behind AtScript would be a huge contribution if it were made in a way where the components that make up the tooling could be mixed and matched for use in novel ways.
You mean, exactly like what the generated JavaScript from AtScript has in the samples shown in TFA?
> The tooling behind AtScript would be a huge contribution if it were made in a way where the components that make up the tooling could be mixed and matched for use in novel ways.
As detailed in TFA, there are two main components that exist right now -- the Traceur transpiler and the RTTS (runtime type system) library, the latter of which provides the kind of functionality you discuss in much of your post. Clearly RTTS can be used independently of AtScript proper.
There are future plans (also detailed in TFA), which include at least one other standalone tool. So the "components which can be mixed and matched in novel ways" seems to be exactly the plan.
If you had spent as much time reading what they actually have done and are doing as you spent writing about what they should and shouldn't do, you may have realized that you were basically asking for exactly what they are doing.
Shameless plug: I wrote a similar library based on set theory (I'm a mathematician)
https://github.com/gcanti/tcomb
EDIT: and here an article explaining the rationale behind the library
https://gcanti.github.io/2014/09/29/javascript-types-and-set...
That would be awkward, especially as your program scales.
/*T (foo: A) => (bar: A) => A */
var func = foo => bar => foo * bar;
Instead of: var func = (foo: A) => (bar: A) => foo * bar;
Handling callback type annotations would make pretty ugly code.. func :: A -> A -> A
func foo bar = foo * barIt seems that this project is trying to build something in between of TypeScript and Dart: they want the optional runtime type checking of Dart vs the good interoperability with JS of TypeScript.
In this interview [1] Anders Hejlsberg and Lars Bak (from TypeScript and Dart) discuss the idea of runtime type checking. They don't seem very convinced of the idea either.
As for the benefits of duck typing, also as I understand it, the key point of runtime vs static checking is that it eases interoperation with non-annotated and non-typed code. So duck-type if and when you want; reap the benefits of types when you want.
For a much better explanation, watch Misko Hevery's keynote about Angular 2 and AtScript from NgEurope yesterday: http://youtu.be/S8fE-w2DL8U?t=21m5s
Looks like they decided TypeScript was Not Invented Here?
[1]: http://blogs.msdn.com/b/typescript/archive/2014/10/22/typesc...
Almost two years in production.
I even had the opportunity to try the F# Type Provider for Sencha Architect and although I do not like tooling I came away shocked at how productive the experience could be for back-end application development using that tool.
You get to leverage the sophisticated type system of F# for your client side code and get transparent interop between front-end and back-end code. There's no need for http/ajax requests to your back-end code because the WebSharper compiler takes care of wiring function calls from the client side directly.
[<RPC>]
let getName() = "David"
[<JavaScript>]
module Client =
let page() =
Div [
Span [Text (getName())]
]
Not only is all of this statically typed, WebSharper takes care of transparently wiring the call for you and serializes any data structure that you may want to pass from the server to the client and vice versa.WebSharper has no problem generating both server-side markup through server-side combinators but truly reigns as a SPA architecture as you can choose to simply return data from your RPC calls and generate the markup on the client-side. Another benefit here is that you generally avoid the need to rely on libraries like JQuery to query your DOM and interact with the markup. Being able to simply keep a reference to any DOM element you create as opposed to having to query your DOM to get is just simpler.
But WebSharper also offer a host of well thought-out abstractions on top of Web Development in the form of Sitelets/Formlets/Piglets and now UI.Next. The real benefit of those is composability.
If you are are already familiar with an ML-like language you will be pleased at the benefits you get. If you aren't, I strongly recommend you take a look at the landscape of programming languages as three great families stand out... you would do yourself a major favor as a developer to learn at least one ML. Those that do never go back.
At [ngeurope](ngeurope.org) Miško pointed out that they we're specifically not aiming to create yet-another-language. Instead they are evaluating ways for JS to evolve beyond ES6 and are planning to propose AtScripts features for ES7 (or whatever is next).
This falls in line with the recent trend that new features start out in transpilers instead of browsers.
Also, only Dart and AtScript are attempts to overhaul/replace JS, Angular is just a library (with versions for JS and Dart), not attempt to overhaul JS.
How? I mean, if they deleted JS from Chrome in favor of Dart (but not AtScript, which is a JS superset) it might break toolchains that developers use, but making Dart (with dart2js) and AtScript available doesn't break anything.
Do we really want to be stuck with a mostly stagnant JavaScript forever? Ugh.
I hate this part about Mozilla and Apple. I dont have qualms about javascript. It has its good parts and as a full time javascript contractor I earn my living with javascript. But... I dont really want the next generation of developers to be stuck with whatever we have today. I am not in favor of "Here is what you get - do all your innovations inside this box" mentality. Yes, there is scope for improving javascript or ECMAscript but there are limits to this. As Peter Thiel says in his book - this is incremental-ism. This will never produce 0 to 1. In order to produce something like that people should be allowed to innovate - even if initially they have to do stuff like this AtScript or Dart or TypeScript! Criticizing those attempts as "breaking the existing tool-chain" is as foolish as criticizing a spaceship because it does not make use of roads.
Currently we are in the midst of writing Angular v2 on top of the AtScript syntax. Here is an inventory of what is working today:
- Traceur transpiler:
- Consumes the AtScript syntax. (type annotations, meta-data annotations, fields)
- Generates ES5 code with runtime type assertion statements for the rtts library and with meta-data annotations.
- Transpiles AtScript into Dart code. (Does not do semantics matching, requires developer to use facades)
- RTTS Library:
- Asserts nominal types.
- Asserts structural or custom types.
- Partial support for generics. Generics support in arrays and maps only.If you look at this page here https://github.com/google/traceur-compiler/wiki/LanguageFeat...
You can see annotations in the "experimental" features list.