Hi Darren,
[...]
> My biggest doubt about what I'm seeing in stratifiedjs is not with
> stratifiedjs itself per se. But doubts whether I could get others I work
> with to see what I see and go with it.
Yeah, whether or not to use something like SJS is definitely a hard
decision. SJS 'solves' one particular class of problems in web apps
elegantly, but of course comes at a price (new syntax, another
dependency to worry about, etc...)
> i.e. the buzz in the more corporate type environments I'm encountering seems
> mostly around angular (first) and then es6/es7 standards (second). And
> those two examples seem to highlight the two yardsticks for adoption I
> always see - either something's already wildly popular and so has a huge
> community (angular) or else that it's a sanctioned standard (es6/es7).
For the past couple of years we've mainly focussed on building a
complete "isomorphic" client/server framework around SJS (see
https://conductance.io or
http://www.infoq.com/presentations/real-time-app-stratified-javascript
- both of these are somewhat out of date unfortunately; only our
github repo is up to date atm; a new release is a few months away). I
think SJS only really unfolds its full potential in this full-stack
scenario.
Most of our recent design decisions in SJS are a direct result of what
we've learned building this framework and applications on top of it.
In particular we're trying to find "universal" abstractions: Rather
than having different domain-specific languages for UI / DB and
everything in-between, we're trying to make SJS expressive and
compositional enough so that a small number of primitives work in many
different problem areas.
Consequently, compatibility with upcoming ECMA standards has taken a
bit of a back seat. We *do* want to be as compatible as possible, but
it just hasn't been a priority lately (especially given that ES6 is
not available on all of our target platforms yet).
There are a few features in ES6 & ES7 that we definitely want in SJS
sooner rather than later (things like the 'spread (...) operator').
In some cases we have added features that diverge somewhat from the
standard (e.g. our template literal & arrow syntax is a bit different
to ES6) and - while I believe in most cases we have found a 'better'
(i.e. more practical) syntax sweetspot - we could be swayed to align
with the standard if there were demand for that.
> So I'm wondering are there any plans for stratified to:
>
> a. adopt the es7 asyc/await keywords? (maybe that's a dumb question - am I
> seeing stratified doesn't *need* such keywords?)
Not a dumb question at all - but yeah, SJS doesn't need async/await.
In a way, in SJS *every* function is automatically 'async' and every
function call is automatically 'await'.
While async/await is a great improvement over the current situation in
JS, it feels very strange when you come from SJS programming. Whether
a function is asynchronous or not is just one of many traits that a
function can have. E.g. a function can be side-effecting or pure. It
can be idempotent or not. Etc. We don't have to annotate functions
with these other traits, so why should asynchronicity be somehow
'special'?
> b. use the es6 template literal syntax? (stratified looks close already
> but didn't I see #{x} not ${x})
We *do* have a simplified version of template literal syntax that
omits the optional tags of es6's syntax. Templates (or 'quasis' as we
call them in SJS) are e.g. used for HTML in our conductance framework
(see e.g. the examples on
https://conductance.io/).
Omitting the tags was a conscious decision - it seems gratuitous
special syntax, as normal function calls can pretty much play the same
role.
(#{x} is for interpolation in *strings* btw - ${x} is for
interpolation in quasis)
> c. use the es6 module syntax?
This is a tricky one. 'export foo' as an alternative to 'exports.foo =
xxx', yes. 'export default' and the full 'import' syntax probably not.
>
> d. use es6 generators for the stratifiedjs streams?
No, unfortunately generators aren't powerful enough to implement the
implicit resource management that sjs streams have (and neither is
async/await).
E.g. in SJS a stream of the lines of a file could look like this:
function lines(file) {
return Stream(function(downstream) {
var handle = fopen(file);
try {
while (!is_eos(handle))
downstream(read_line(handle));
}
finally {
close(handle);
}
})
}
When we use this e.g. like this:
lines('foo.txt') ..
transform(line -> line.length) ..
each {
|length|
if (length > 80) {
console.log('warning, line width exceeded');
break;
}
}
Then, if we hit the length > 80 condition, the break will not only
bail out of the block, but also cause the file to be closed (by
implicitly executing the 'finally' handler).
You would think that you could code something similar with generators,
but it turns out you can't - see
https://groups.google.com/d/msg/stratifiedjs/IULlfOt1A6w/cXtBx1byIFYJ
> e. es6 style arrow functions (i.e. (x) => {...} ) in place of the ruby
> style blocks? (i.e. {|x| ...})
> (I see there's coffeescript style arrow functions i.e. -> I might not be
> appreciating the difference yet between the arrow functions and the blocks)
SJS has both -> and => (the fat arrow binding 'this'). They are both
intended for small expression-based functions (and, in constrast to
the ecma standard, the right side needs to be an expression, i.e. must
not contain statements like 'if', 'while', etc).
The idea behind block lambdas is that they behave very similar to
normal JS blocks (a block is e.g. the `{...}` in `while() { ... }`).
In particular 'break', 'continue' and 'return' work in a way to make
it possible to write looping constructs that almost behave like native
'while' or 'for' constructs. Consider e.g. this function that loops
over the elements of an array:
function forEach(arr, f) {
for (var i=0; i<arr.length; ++i) {
f(arr[i]);
}
}
With normal functions, we have no simple way of breaking out of the iteration:
forEach([1,2,3,4,5],
function(val) {
console.log(val);
if (val === 3) break; // doesn't work. 'return' doesn't work either
});
With block lambdas, this works just fine:
forEach([1,2,3,4,5],
{ |val|
console.log(val);
if (val === 3) break;
});
> Thanks and stratifiedjs really does look good to me (I've been tinkering
> with enough of with alternatives - generator based task runners, the js-csp
> channel approach, react and angular, etc. - to recognize the value of what's
> here).
Thanks :-)
Cheers,
Alex
--
Alexander Fritze
http://onilabs.com