Imba – A new programming language for the web
imba.io
imba.io
React is a template library, not a language.
JSX is a way to write templates, but that's not react, and its not what react does. It's just a shortcut to writing XML.
You could say this is a competitor to JSX, perhaps; but anything more is hyperbole.
People aren't using react and angular because they have a nice syntax, that's just nice, they use them because you can build applications with them.
How do you build ui components using imba? Use react? :P
You build UI components like this:
tag event < div
def render
<self>
<h1> event.title
<p> "Happening on {event.dateString}"Read what I wrote again.
You just wrote a template. That's like JSX.
You ALSO need a library to do the virtaul dom stuff and/or data binding to write an application.
React. !=. JSX.
What you have here is a programming language that compiles to javascript and has an inbuilt templating language. So does ES6; `${hi}`.
That's a fundamental building block, not a replacement for a high level framework, like react.
You say:
>You ALSO need a library to do the virtaul dom stuff and/or data binding to write an application.
OP says:
>Imba includes syntax for tags (scroll down to "Tags"), virtual DOM diffing, event handling (with touch support).
>Although Imba was started before React it should be noted that it didn't include virtual diffing until React showed that it worked.
If he was unsure about what he saw in those examples, then he could always refrain from pissing on the project until he had more information.
Still... I suppose that my original post remains the top here says something. Cant reedit something with no parent. too bad. ;)
1. how much of the speedup is due to replacing JSX, and how much due to replacing the diffing algorithm.
2. how do you improve on the diffing speed, is it due to immutable data structures underneath, or something?
3. do you also provide mount/unmount hooks for the components?
http://imba.io/#/examples/todomvc/app.imba (this annotated app is illuminating, and ought to be put upfront on your site if possible)
The methods are clean and readable:
tag #app
def dirty
persist
render
def add title
if title.trim
TodoList.push(TodoItem.new(title.trim))
dirty
self
And the view+rendering (literally the whole "upgraded-HTML" of the app) is so compact: def render
var all = TodoList
var active = all.filter do |todo| !todo.completed
var done = all.filter do |todo| todo.completed
var items = {'#/completed': done, '#/active': active}[hash] or all
<self>
<header.header>
<h1> "todos"
<new-todo-input.new-todo type='text' placeholder='What needs to be done?'>
if all:length > 0
<section.main>
<input.toggle-all type='checkbox' :change='toggleAll'>
<ul.todo-list>
for todo in items
<li[todo]@{todo.id} .completed=(todo.completed) .editing=(todo.editing) >
<div.view>
<label :dblclick=['edit',todo]> todo.title
<input.toggle type='checkbox' :change=['toggle',todo] checked=(todo.completed)>
<button.destroy :tap=['drop',todo]>
<edit-todo[todo].edit type='text'>
($$(.todoapp) or $$(body)).append #app
I'd enjoy being able to code a SPA like this, I think - nice work! If something this clean is already possible in some other language/framework/library, I'd love to hear about it (since I haven't been following recent JS developments closely).edit: @judofyr, the Scroller example app doesn't work for me on Firefox 40.0.2 on Win 8. It works in Chrome.
- the appropriate method is called [e.g. add]
- which mutates the state [e.g. TodoList.push(TodoItem.new(title.trim))]
- and then render is called, which updates the view/DOM
So in a sense it's not really data-binding, IMO - instead, the render method contains the entire view + view logic, and it gets called each time the state is changed.
That's not to say I wouldn't be interested in reading about a language that could somehow compete with Vim, if that was an accurate statement.
It does appear to have a React-like engine here: https://github.com/somebee/imba/blob/master/src/imba/dom.sta..., but from a quick glance, I can't tell if the quality of the engine is any good (e.g. whether it supports lifecycle methods, efficient sorts, jQuery plugins, etc) because there are no docs and I don't really have time to read the whole codebase right now. Same goes for the speed claim: can't tell if it's actual speed or "cheating" by batching multiple redraws on rAF while not batching them in the React demo. I'm guessing the latter.
Also, I'm not sure I agree with claim of readable output js: http://somebee.github.io/todomvc-render-benchmark/todomvc/im... (look at tag.prototype.render). It's not exactly clean, although it's not terrible either.
With that being said, the language does look like it has some improvements over Coffeescript. The lack of docs is a showstopper for me, however.
That's a fair criticism. We know that docs are severely lacking. But at one point you'll have to release it. The reason it's been private for all these years is because there's always been just one more thing to fix.
And this is just an open-source project. We just think this is a cool technology and want to share it with the rest of the community.
> Same goes for the speed claim: can't tell if it's actual speed or "cheating" by batching multiple redraws on rAF and while not batching them in the React demo. I'm guessing the latter.
Hah, we talked about this before the release. We actually thought about publishing worse results (or adding some code to slow it down) because we were afraid people wouldn't believe it.
requestAnimationFrame isn't used in this demo. The repaint/redraw is not the thing we are trying to benchmark. We might as well hide the whole app during the benchmark, or even detach it from the document. It is trying to measure the performance of bringing the whole view "in sync". If there is something wrong with the way Mithril is forced to render, please file an issue.
> lifecycle methods, efficient sorts, jQuery plugins
There's probably some more lifecycle methods that could be useful, but the amount of lines written in Imba is in the magnitude of 100k. The current approach has been adequate for that.
The sorting is quite efficient. We find the minimal amount of nodes that needs to be reordered. jQuery plugins should work fine as long as they don't touch the parents too much; Imba is quite good at keeping the DOM-node in the tree.
> requestAnimationFrame isn't used in this demo
Interesting. Gonna look into the project more when I get a chance then.
jQuery plugins, from my own experience, are quite naughty. Modals, tooltips and drag-n-drop things are examples of things naive people might try to throw at the system and wonder why things get wonky.
I just commented below after looking over their benchmark. In it, the Imba implementation, and it alone, is caching and reusing the rendered todo views (globally, forever -- hello memory leak). Without that, they're only 2x faster than React and Mithril, not 60x.
rAF batching isn't an issue. They perform a render(true) after each change, effectively making all frameworks work synchronously.
Other than that, it is an interesting framework, and I wish them well.
I'm really glad to hear that it is still faster even when removing caching. That, to me, is quite insane. But if you wrote a TodoMVC app in Imba, you would do it _exactly_ like the one that is benchmarked. We have even considered adding asserts to warn users if they use uncached nodes in rendering that happens very frequently.
You are actually right that Imba does not dereference these automatically (see other comment re purging by judofyr: https://news.ycombinator.com/item?id=10092454). We could dereference unused tags once every second or so, but for now we think it is better to have manual control of this. Again, how much is usually happening during a render-cycle? Basically nothing. This benchmark is trying to look at how expensive it is to rerender the whole view. Maybe I should make the "Unchanged render" benchmark the main attraction (as it is the most important) -- but it is quite boring to look at.
You are absolutely right, and I agree. When you use static tag trees in Imba (with inline caching) the code is not readable. If you only use it for regular things you would write in js (classes, functions, etc) I still think it is quite readable.
BTW, I really love the simplicity of Mithril. It is a very impressive project.
Yeah, for non-tag stuff, the output does look clean. I mentioned this for tags because I didn't see source maps. Transpiled code needs to either output source maps or it needs to be reasonably traceable-by-hand back to the source of a bug (say, in the case a null ref exception)
Perhaps you haven't looked at the examples.
>React is a template library, not a language.
Irrelevant -- and it's not such a clear cut distinction as you make it anyway.
A new language can have built in first class support for react like templating -- and this does.
>People aren't using react and angular because they have a nice syntax, that's just nice, they use them because you can build applications with them.
Yeah, so the idea behind imba is that if you could do the same things WITH a nice syntax and first class support it would be better.
Seriously do people read TFA?
The vast majority of the speedup comes from a single sneaky line of code. The majority of their "Everything" benchmark's time is spent in the reorder step. They've implemented this as "remove a random todo, render, push the removed todo back onto the end, render." The Imba implementation, and it alone, caches the rendered todo view, so that they can re-use it once the todo is reinserted.
This single optimization is responsible for the vast bulk of their claimed speed. Removing it puts Imba only 2x faster than React, not 60x.
If you want to try it yourself, look at line 55 of app.js. Change:
res.push((this['_' + todo.id] = this['_' + todo.id] || t$('todo')).setObject(todo).end());
... to: res.push(t$('todo').setObject(todo).end());
Furthermore, this isn't a caching strategy you'd want to use in a real app. It holds onto all DOM nodes ever created, thereby leaking quite a lot of memory.Again, I think Imba is cool, and fast, just not otherworldly fast. I hope this was just an "oops!" and not an intentional misrepresentation.
This is utterly wrong, and if you had cared to read about what the benchmark is trying to achieve, you would understand (https://github.com/somebee/todomvc-render-benchmark).
You cannot simply remove caching and reusing nodes from the benchmark (which you do with that change). This is the way Imba does diffing, and it would be akin to removing the React virtual dom!
As we mention in the readme: "Even though it looks incredibly boring, the "Unchanged Render" is possibly the most interesting benchmark. All of these frameworks are plenty fast if they only render whenever something has changed. But if the frameworks are fast enough to render the whole app in 0.01ms, you could skip thinking about all sorts of tracking to keep the view in sync."
In a real world app you do not create 1000000 todos. The actual data rarely change that much. As for purging the cache, see comment: https://news.ycombinator.com/item?id=10092454. Quote:
One thing to be aware of is that Imba doesn't automatically remove the cache for you, because we've found that it's tricky to determine when you actually want to purge it. For instance: if mouseOver <something> else <something-else> Just because `mouseOver` becomes true for one frame doesn't mean you want the `<something-else>`-tag to be purged from the cached and removed. Keeping it around is nice for performance and convenience (e.g. state, jQuery plugins). In practice it turns out you want to purge whole pages/sections at the same time, which is way friendlier for the garbage collector as well.
If you _really_ want to not cache things this way, you can change the line to:
res.push((this['_' + i] = this['_' + i] || t$('todo')).se ...
Which would only ever cache as many dom nodes as there are tasks, but change which nodes are used for which tasks.UPDATE: Since the performance was just as good with this dumber type of caching I have changed the actual benchmark to work this way. Would you still consider that caching sneaky? If so, I'm not sure what to say. Yes, Imba caches dom nodes for reuse. That is the whole philosophy behind its 'virtual dom'. Now it does not 'leak memory' anymore either, even though this 'leak' is a feature (ref comment about manual pruning) and not a bug.
Having tags as a proper part of the language is very nice. This just works in Imba:
<ul>
for event in @events
<li>
if event:type == "like"
<like event=event>
elif event:type == "comment"
<comment event=event>
In React I'd have to use `map` and refactor parts into variables. I've been struggling to use React on teams with designers because small design changes can cause rather huge changes in how the code is structured.Other than that you can think about it as indentation based JavaScript with implicit method calling (`foo.bar = 123` calls the setter `setBar`) and saner handling of `this`.
The only new thing JSX brings to the table is the element syntax. And all that does is translate `<a b={c}>{d}</a>` to `React.createElement(a, {b: c}, d)`.
{ul, li} = React.DOM
# require in like and comment components here...
ul {},
for event in @events
li {},
if event.type is "like"
like {event: event}
else if event.type is "comment"
comment {event: event}Imba was started before React was available so it wasn't an option back then. As for today, the language integrates tags in a much nicer way than what's possible with CoffeeScript + React. This especially pays off performance-wise.
Although Imba was started before React it should be noted that it didn't include virtual diffing until React showed that it worked.
EDIT: But yes: Docs are lacking, and that is a reason for you to not pick Imba for a project right not. We'd still think it would be worthwhile for you to checkout though. There's some interesting ideas in there.
I quote:
"Imba is a new programming language for the web that compiles to performant and readable JavaScript."
Ok, so i understand Imba is a language spec with an implementation that compiles to javascript. "It has language level support for defining, extending, subclassing, instantiating and rendering dom nodes."
Ok so there is special syntax to create DOM elements. Nothing new here. Its just syntax over javascript. What can be done with imba, can be done with vanilla javascript. "it is more than 20 times faster than React"
Wait, what? React is a javascript library, not a programming language. Written in javascript.... How can Imba be faster? Does Imba also include a dom-diffing algorithm.. If so, why would you built that into the language... Woudnt it be better to write a library in imba-lang that can do dom diffing? I'm lost here.Yes.
> Woudnt it be better to write a library in imba-lang that can do dom diffing?
It is: https://github.com/somebee/imba/blob/master/src/imba/dom.sta.... It's a required runtime library if you want to use the tag syntax.
The difference between "language" and "core library" is always a bit mushy. For instance, the JavaScript doesn't only specify the semantics of operations, but also the main objects (String, Array, etc) and a set of functions (push, pop, indexOf, etc).
In the sense that JavaScript ships with default objects for dealing with Arrays and Strings, Imba ships with default classes for dealing with tags and DOM elements. Yes, we could say that tags should just be sugar syntax over regular function calls (which it actually is) and move the DOM diffing out of "Imba". But really, the main point about Imba is the tag functionality and we believe we only need one good implementation.
"For a semi-complex application like TodoMVC, it is more than 20 times faster than React with less code, and a much smaller library."
I think the comparison makes sense because Imba seems to imply a lightweight framework. At least, the generated code in the examples on the front page references a `t$` function, which has to come from somewhere.
There are certain best practices that have emerged for general purpose languages. Imba is not a general purpose language; it's explicitly meant for web programming, and makes sense that it would build common web programming functionality into the language itself.
The same way an advanced primitive in a language can be faster than another language + framework code to do the same thing.
What exactly is startling? It's not like languages/libraries and frameworks have some hard defined boundaries. What's a library for one language can be built-in primitives for another (e.g. consider using vectors and hashmaps in C vs Python, or consider something even more powerful like APL or Rebol).
>Does Imba also include a dom-diffing algorithm.. If so, why would you built that into the language... Woudnt it be better to write a library in imba-lang that can do dom diffing?
No, it's not always better to have "a library" vs first class support. Not to mention that some things are impossible to do with regular user code in a language vs first class code (e.g. consider how Go's make() is "blessed" to work as a generic function).
Especially here, where the whole purpose of the language is to be a DSL for web programming and to incorporate all these conveniences.
Nothing new either: we have had languages with first class support for specific use cases since at least the 60's.
Let me guess!... CoffeeScript?
- Implicit calling: `foo.bar` calls `foo.bar()` and `foo.bar = 123` calls `foo.setBar(123)`
- Objects have instance variables that's separate from the methods. Well, technically the instance variable `@bar` is just stored as a property with name `_bar` on the object.
- Variables must be declared with `var` and they correctly shadow previously defined variables.
- `do` provides a syntax sugar for the pattern "function as the last argument"
- Optional arguments work together with block parameters
def timeout(amount = 0, &cb)
cb(amount)
Compiles to: function timeout(amount,cb)
if(cb==undefined && typeof amount == 'function') cb = amount,amount = 0;
return cb(amount);
};
- `self` is a keyword which is a saner `this`, and instance variables are automatically looked up using `self`: def end
@client.on("end") do
@server.end
Compiles to: function end(){
var self=this;
return this._client.on("end",function() {
return self._server.end();
});
};Wuhh. Why wouldn't you use JS defineProperty here?
Semantically the biggest difference is that you don't need to do anything special for marking a method as a property:
class List
def length
# …
In this case `list.length` just works. The disadvantage of this is that if you want to get the function itself, there's a separate syntax (`list:length`). Other than that, this is mostly about taste/style.1. Why differentiate it from CoffeeScript so much? Why not call it DOMCoffeeScript or something? Are there any core language changes from CoffeeScript other than the tag features?
2. I'm not sure how I feel about the mixture of XML tag characters with HAML/Jade-like indentation. My gut instinct is to always look for a closing tag with XML/HTML. Why not use some kind of sigil like % or @ or ! to represent a tag, since clearly the requirement for both a left and right caret is now obviated?
3. Why require the `var` keyword instead of making it the default? That's one of my biggest pet peeves with languages like Javascript and Lua. Local-by-default always makes the most sense.
2. It's still nice to separate the attributes from the content:
<h1 title="hello"> "Foo"
Why use a new syntax when everyone knows HTML/XML?3. The lack of `var` in CoffeeScript is its worst feature ever IMO! Every time I write `someVariable = …` I'm terrified that I will accidentally overwrite a previous variable. Imba improves on JavaScript here and will correctly shadow multiple `var` in the same function.
<label>
<input:checkbox:checked#myCheckbox>
<span> Some Text
Might be nicer than actually spelling out the attributes and properties, if you're taking an already wrist friendly language and bolting on tags, then taking that a step farther would probably be a nice idea as well. <label#foo.bar .baz=isBaz> "Label"
compiles to: ti$('label','foo').flag('bar').flag('baz',this.isBaz()).setText("Label").end()
where `flag` is a method which adds to the class list (unless the second argument is falsey).But for 3... so you never use languages like Ruby or Python? Variable assignment shadowing is always possible in those languages, yet for seasoned developers, it tends not to be a real issue.
Now they created a new "nonlocal"-keyword to cope with this but it wasn't added until version 3.0. https://www.python.org/dev/peps/pep-3104/ has a great summary of all this.
var answer = if number == 42
The language looks shockingly pleasant in a number of ways, but everything being an expression seems odd. Would somebody mind helping me understand the value (semantic, performance, etc.) of such a choice? doSomeThing() unless person.present
For me that utterly destroys readability - in my mind, when I see a (), that function is being called there and then. The fact that you can invalidate that later in the line confuses me deeply - and it doesn't really provide any benefits above an if statement anyway.The rest of CoffeeScript is great though, don't get me wrong. (though ES6 JavaScript has taken the best features anyway)
something() if False else y
The `something` function is never called.It fits the style of Ruby to try and cut down on syntax noise where it's not needed. Contrast:
save! if !record.persisted? && !record.invalid?
save! unless record.persisted? || record.invalid?
Though I do appreciate it's a bit unusual compared with most other languages – CoffeeScript does owe a lot to Ruby's syntax. if !record.persisted? && !record.invalid?
save!
or: unless record.persisted? || record.invalid?
save!Another way to look at it is why do you think the conditional should come before like you've shown? Because C or even older languages started with that? If you didn't have prior experience with that form, would you still think it's inherently better, or would the trade-offs between the two forms seem slightly more balanced?
The same applies to while/until loops, which can lead to quite succinct code.
I've been using it for a long time, so I don't find it confusing at all – but I agree it's pretty rare to find, so I'm not surprised to find out some people would rather not see that!
For example, they work really well in loop control statements:
for my $i (1 .. 100) {
next if $i == 10;
next if skippable($i);
last if is_what_we_want($i);
# Do stuff here
}
Or more complex param validation sub foo( $arg1, $arg2 ) {
return unless $arg1 > 10;
die "Invalid argument arg2!" unless defined $arg2 and $arg2 =~ /^(?:CAT|DOG|GERBIL)$/;
# Do something
}
That said, I don't like it for assignment of in that manner (at least where the assigned value comes out of the if), because the main justification for allowing it (it's a natural extension of how we think) doesn't follow. A ternary operator is better in that instance, IMHO.A major semantic benefit of expression-oriented programming is minimizing state while maximizing composition (e.g. compare and contrast a switch statement to pattern matching).
It's aligned with a general approach of reducing syntax noise, and it can result in some really nice, clean code. It leads to a whole class of syntax possibilities, like implicit returns.
There are probably some performance arguments against this in the case of Coffeescript, especially wrt constructing expensive return values that are immediately discarded. The consistency is nice, however.
$v = 1 if $v < 1;
return unless defined $param;
die "died!" unless $param > 10;
But you cannot: $v = if $v;
You also cannot use else on postconditionals (if it's that complex, you need a traditional if statement). x = (:false if true)
=> :false
x = (:false if false)
=> nil
Any other if statement does appear to be treated as a value: x = if true then 5 else 10 end
=> 5 my $x = 1;
$x = 10 if $x > 1;
say $x; # 1
Personally I find the assignment of the if/else statement's return value distasteful, as it's both complex to read and mixes a portion of a natural pattern of thinking while later abandoning it, making it unintuitive. At that level, I prefer a ternary operator.EDIT: of course, there's Smalltalk, where postfix conditionals and loops are the only form available. Maybe Ruby got inspired by those.
This looks like a nice modern syntax which is both an ES6 focused minimal JS (removing unnecessary tokens) with HTML building included.
Imba only uses `===` for diffing. If you want Imba to re-use a DOM node, you must use the same tag object. Imba provides syntax for caching nodes as properties on the current object.
For instance, in order to re-use DOM nodes in a for loop you do this:
for event in @events
<event@{event.id} name=event.name>
The loop body compiles down to: (this['_' + event.id()] = this['_' + event.id()] || t$('event')).setName(event.name()).end()
The next time you render the view, Imba will find the tag objects that have been reordered (using `===`) and move them to the right place.One thing to be aware of is that Imba doesn't automatically remove the cache for you, because we've found that it's tricky to determine when you actually want to purge it. For instance:
if mouseOver
<something>
else
<something-else>
Just because `mouseOver` becomes true for one frame doesn't mean you want the `<something-else>`-tag to be purged from the cached and removed. Keeping it around is nice for performance and convenience (e.g. state, jQuery plugins).In practice it turns out you want to purge whole pages/sections at the same time, which is way friendlier for the garbage collector as well.
I like the way it looks. A lot. Love, love the tags. Really like the simplified object literals. The use of global variables for class state is deeply troubling - they are not scoped at all. The parser is far too forgiving. if you change do |x| xx into something like do x xx it will compile fine, but be wrong. The tooling is quite nice, and I like the defaults - although it's still a little bit of a mystery where the imba.js file comes from in the Hello World browser example (I ended up just copying it from Github). I'd like to see argument comprehensions, and the option to generate code outside of an immediately excuting function (so I can play with instances at the dev console)
I would like to see a "strict" mode for imba that chokes on a do block without pipes, for example. I think that if JavaScript has taught us anything it's that anal compilers might frustrate us at build time, but that frustration is nothing compared to the frustration down the line when things break at runtime.
class A
var i = 10
var i = 20
Compiles to function A(){ };
var i1 = 10;
var i = 20;
So they are actually scoped even though it does not look like it in the compiled js. I'm looking really forward to improving the sublime plugin to show much more stuff from the compiler and warn about calls to undefined methods etc. There is a lot of analysis from the compiler that can be used to improve the ide-like experience. class Todo
# variable defined in class scope
var count = 0
Which compiles into this: var count = 0;
And also your example page elides the IIFE that your compiler surrounds all output with, implying (falsely) that it's global.As for ST, I think that for me based on my brief experience, you might want to add more compiler warnings to the watcher. (Basically I messed with Imba locally with two ST windows side-by-side, looking at Imba on the left and js on the right, treating the watcher output as compiler output.) Don't get me wrong, ST feedback is great, but the watcher feels more canonical. Besides, not everyone has ST!
Plus, I love the fact that the syntax looks Pythonic :)
1. It store the previous rendered tag and does a diff. (Just like React).
2. Every tag is compiled to JavaScript that's easy for the optimiser.
tag event < div
def render
<self>
<h1 bar="123" baz=bar> "Hello world!"
Compiles to: // Setting up the tag-object. Then:
tag.prototype.render = function() {
return this
.setChildren(Imba.static([
(this.$a = this.$a || t$('h1').setBar("123")).setBaz(bar)
], 1))
.setText("Hello world!")
.synced()
}
While React passes an object of props around, Imba will instead call setters. These setters are very easily inlined by modern browsers. Also note that it caches directly on the tag object itself which gives another additional boost. Since it caches the objects themselves it can also compare everything with `===` and/or `indexOf`.The `Imba.static`-call marks an array as static which is a guarantee that the structure of the array won't change. In this case Imba will not do the full diff-algorithm, but instead compare each item element-by-element.
And yes, once you've achieved the minimal amount of DOM changes needed (like React), the next step for performance is all of these little tweaks. Does it matter? It all depends. Imba is capable of rendering bigger applications than React when you use the "render everything over again in the animation loop".
TLDR: The tags are more integrated into the language. The language is also designed around features that's easy for the optimiser.
Similar idea but just ads JSX tags to Coffeescript (cjsx).
Only ergonomics problem is that the syntax highlighting sometimes breaks on single quotes used within the XML tags so you end up having to do something like `<p>{"you're fired"}</p>` so that it doesn't mess up the highlighting in your whole file.
If the answer is "instead," is it a language and a view framework?
Also, for React applications I've found that LiveScript (a functional compile to JS language) makes for a great JSX alternative as shown here: https://arch-js.github.io/docs/02-basic-tutorial.html
"If you mess up your indentation, you're in hell."
"Tabs or spaces? If the latter, how many of them?"
"On what particular character will I be able to hit % to find where the related block is started?"
...
dom`<div> ${contents} </div>`
As far as I can tell on a quick google, this remains to be done. (I saw some hits for HTML string templates as opposed to direct DOM construction.)Unsure of what use it would be, but nice for a change.
More like, "Imba is a new syntactic 'skin', which transliterates to JavasScript."
All of which is a long winded example to get back to the idea that the translation/transliteration difference is very similar to the compilation/transpilation difference and while I don't think we've yet seen a cultural battle for supremacy between the terms, I do think there is a usefulness in keeping the distinction. I also see the conversion between idioms/abstractions as being the key difference between compilation and transpilation. Machine language has much different idioms/abstractions from a high-level language; CoffeeScript and TypeScript try to stay very similar in idiom/abstraction to EcmaScript.
I think this is either developed by or targeted at people with a ruby background, and does give some context. I'm actually more happy with something closer to JS (EX6/7 transpiling) with React (JSX) than something like this. Usually when you approach headaches on larger teams with JS, it's more that you haven't broken things down as well as you can/should more than a language construct.
JS projects tend to work far better from discrete separations of components, views, functions and composites... simple components can be thought of react components that only use properties for rendering, views are a composition of components that use stores for state interaction. Functions are modules that have singular discrete testable functionality and composites are similar to classes but yeild an object tethered to state/options but mainly glued together from modules that expose a single workflow function.
There's also control/workflow type composition, and node-style object pipes tend to work very well in many of those scenarios... get batch of items from db into an object stream through workflow steps, queues, etc.
It's definitely an interesting abstraction of a few ideas together, I'm not sure what it does in terms of improving a larger workflow. Other than a more wrist friendly syntax.
It might be more effective for you to use your time understanding why these aspects are important, since you apparently feel this project is good, and less time being a bit of a dick about it.
By Ruby programmers. Why is it that Ruby programmers are incapable of imagining anyone doesn't love Ruby?
This isn't a universal truth for all programmers either. I've met plenty Java programmers willing to admit the shortcomings of Java, I've met PHP programmers painfully aware of the language's warts, I've even met Python programmers willing to admit Python's limitations. I've yet to meet a Ruby programmer who doesn't believe that Ruby is the best thing since sliced Jesus.
As well as by not-Ruby programmers, which is why they keep getting used in non-Ruby languages that don't keep other aspects of Ruby.
> Why is it that Ruby programmers are incapable of imagining anyone doesn't love Ruby?
I think most Ruby programmers are capable of understanding that lots of people don't like Ruby, and more importantly that lots of people don't like aspects of Ruby that those Ruby programmers find most attractive.
Sure, some Ruby programmers have problems with this, but, OTOH, some non-Ruby programmers seem incapable of understanding that other non-Ruby programmers might find some aspects of Ruby attractive that they, themselves, do not.
> I've met plenty Java programmers willing to admit the shortcomings of Java
Well, sure, the more likely you are to be compelled to use a language because of corporate inertia, the more likely people that actually do use it will be the people that don't like it and use it under duress. So I'd expect Java to be among the languages with the highest proportion of active programmers who not only are willing to admit its shortcoming, but who outright despise it.
> I've yet to meet a Ruby programmer who doesn't believe that Ruby is the best thing since sliced Jesus.
Given the number of non-Ruby programming languages created with substantial input from (or even under the leadership of) people in the Ruby community specifically because, while they like many things about Ruby, they find it not optimal for some uses, I think this says a lot more about your limited exposure to the Ruby community than about the Ruby community itself.
And clearly other people – or we wouldn't be seeing those syntax elements in other languages.
Why is it that Ruby programmers are incapable of imagining anyone doesn't love Ruby?
They're perfectly capable of that, and I think you've let your own prejudices cloud your judgement.
I've yet to meet a Ruby programmer who doesn't believe that Ruby is the best thing since sliced Jesus.
Hello, pleased to meet you. I'm a mostly-Ruby programmer who is well aware that the language is not suited to every task. Need high performance? Look elsewhere. Need a highly reliable service? Something that would benefit from static typing? Systems-level tools? Same. Ruby is a pain to deploy and has lots of irritating legacy cruft.
What this doesn't mean is that the statement "that pile of junk that is ruby" is anything other than a fucking stupid thing to say.
With ES6 and Babel this "new programming language" provides nothing interesting other than making your code look more like Ruby.
I would appreciate it if people knowing very little about programming languages stopped commenting on new languages. Nearly every comment here is either baseless or irrelevant or simply wrong. It's frustrating.
In your specific case: CoffeeScript and this are most certainly not a "JS-based implementations of Ruby." This is: http://opalrb.org/
And how the language "looks" - its syntax - does matter, but not in the way most people think it matters. It's just that the syntactically simpler constructs tend to be used more often, so the choice of syntax affects the code people write. The rest, including "readability" or simply "beauty", is meaningless in the long run.
EDIT: I'm in no way involved in this project!
And the point is that it goes out of its way to re-invent features already supported by ES6 just so they look more like Ruby. Like using string interpolation instead of template strings, for example.
It's not a language built on top of JS to improve upon JS, it's just as contrived as CoffeeScript (which unlike this one actually had a reason to exist in that it influenced the development of ES6 when a lot of features it implemented weren't yet part of JS).
What is the benefit of learning this language? Who is this for? JS programmers? No, they could just use Babel to write something that will eventually become vanilla JS.
Does it bring anything new to the table like ClojureScript or LiveScript does? No, it's basically CoffeeScript with ES6 scoping rules and JSX elements.
So in the end all it adds is another barrier to entry for new developers joining your project/company with the only benefit being that it's "prettier".
I'm not saying bad ideas aren't worth exploring -- they are, and if your bad idea happens to involve creating your own programming language, all the more power to you. But the only "good" reason to use this language is if you want your JS to look like Ruby.
Just like Haml is for people who want their HTML to look like Ruby; and like Sass (not SCSS, I mean the original braceless syntax) is for people who want their CSS to look like Ruby.
* REST * Many parts of ES.next * Front-end build tools * CSS pre-compilation * JS transpilation
I spent years happily using multi-line template strings while JS developers informed me how idiotic I was for using a transpiler. Since Ruby's goal is to be a language that brings joy to the user, I see nothing wrong with bringing that ethos to other languages. You yourself acknowledge the impact it had on the development of JavaScript.
We in the Ruby community will keep innovating, and you keep hoping that we'll stop, and we'll see which happens.
What the f* are you on? Or were you born a few years ago and just worked with Ruby since then?
Really, how could somebody be so oblivious to this field in order to state stuff like that?
> What the f* are you on? Or were you born a few years ago and just worked with Ruby since then?
I've been using Ruby professionally for 10 years.
How about the whole WSDL/SOAP services that appeared way before that? You're telling me that Rails was the one who came out with the modern REST ideas?
That's total tech illiteracy right there. Damn, you even had the nerve to defend that feeble argument.
Well if you define REST as "Web Apps developed with RoR" then I guess you're right, Rails is definiteley the pioneer of Rails development.
>You've yet to refute that argument
There was (at least) Tomcat deployed and quite popular, and yep, everything moved through REST interfaces. Even with that one and the huge success it had in the enterprise world, I wouldn't dare to say that the success of REST relies on Tomcat anyway.
REST hit it big with the www, www is REST's killer app. Those things are quite literally the first ones you should know when you start developing for the web.
Automagic REST APIs may be easier to do with "RESTful" MVC frameworks but what you really want is a domain-oriented REST API. But I digress.
> The funny part is that technically Rails and Rails-inspired REST frameworks get it wrong.
Well, that's a bit tangential to my original point. I wasn't claiming that you specifically liked the way it was implemented, just that Rails, and thus the Ruby community, was responsible for its popularity. Despite the length of this thread, neither of you has managed to debunk that claim with anything resembling evidence.
Find a reference to Tomcat using REST before 2007, and give us the link. I'd bet you can't, since Rails was the first major web framework to implement REST.
> REST hit it big with the www, www is REST's killer app.
Since REST was invented in 2000, and the web itself had been around for a bit before that, I fail to see how this could be true.
- https://en.wikipedia.org/wiki/Representational_state_transfe...
"The first edition of REST was developed between October 1994 and August 1995, primarily as a means for communicating Web concepts as we wrote the HTTP/1.0 specification and the initial HTTP/1.1 proposal. It was iteratively improved over the next five years and applied to various revisions and extensions of the Web protocol standards."
- Roy T, Fielding, Architectural Styles and the Design of Network-based Software Architectures, 2000
Most interesting is Roy's presentation at RailsConf Europe in 2007 (http://roy.gbiv.com/talks/200709_fielding_rest.pdf):
Use your brains!
- don’t design-by-buzzword
- don’t believe everything you read
No. Rails populated a form of REST and everybody likes to pretend everything Rails is REST and there are a ton of frameworks trying to imitate Rails' approach to REST but Rails neither invented REST nor was it the one thing making REST popular. It was a major factor, yes, but claiming this purely as an accomplishment of Ruby is silly.
I would be willing to give Ruby the point for MVC because of ActiveRecord but MVC is not synonymous with REST.
> Many parts of ES.next
Again, no. ES.next is nothing like Ruby. Some of the syntax was influenced by CoffeeScript (nobody doubts that -- in fact, TC39 members have explicitly referenced it on more than one occasion) but the features are neither novel nor unique to Ruby:
* The class syntax is pretty much universal.
* The arrow functions are evidently influenced by CoffeeScript but look nothing like Ruby's lambda literals (which are the closest equivalent in Ruby). I think CoffeeScript's use of that syntax was actually pre-dated by C# but I may be mistaken.
* Template strings have no more in common with CoffeeScript's and Ruby's string interpolation than with the same feature in other languages. In fact, if anything, I'd say the interpolation syntax is borrowed from PHP -- but the backticks certainly aren't taken from any of them.
* Symbols are kinda like Ruby symbols if you tilt your head and squint really hard and then only focus on the name and not what they actually are. Again, the concept is neither novel nor unique to Ruby.
* Destructuring and rest/spread operators -- yeah, again, not unique or novel. Plus I think even Python preceded Ruby on that.
* iterators and generators -- again, closer to Python than to Ruby.
* import/export -- just an extension of the ideas of CommonJS which in turn aren't anything like what Ruby has.
* promises -- no, sorry, not Ruby.
* the object literal extensions -- again, not Ruby. Ruby doesn't even have object literals in the sense JS does (which is okay, it doesn't have prototypal inheritance either).
> Front-end build tools
No, seriously not. Yes, rake pre-dates grunt and gulp by a fair amount (as well as jake and other JS-based tools barely anyone seems to use anymore). But it certainly didn't invent them nor was the biggest factor in popularizing them. A lot of build tools before the Ruby (and now JS) toolchains came along were built in things like Java, in addition to the various less formalized build tools written in Python or simply bash.
> CSS pre-compilation
I may give you that. Less pre-dates Sass but started as a Ruby gem. Of course neither of them invented CSS minification and there were attempts at generating CSS before. Compass probably took the crown, though, even though front-end tools in generally have moved on to the Node ecosystem, which seems more appropriate for tools primarily concerned with JS (rather than Ruby, Java or bash).
> JS transpilation
Not really. Java-to-JS transpilation was the original hotness that opened up people to the idea. It was followed by various attempts to port other languages to JavaScript. I agree that CoffeeScript is the first one that gained major traction in the startup scene -- although most teams seem to have realised that the drawbacks aren't really worth it (not just the transpilation but the entire part where everyone has to learn a new language on top of a solid understanding of JS itself).
Yes, CoffeeScript was an important step in the evolution of JS but so were DHTML, pop-unders, JSS and animated mouse cursors and status bars -- and everyone agrees those were a bad idea.
The Ruby community is very vocal and self-important but it's neither as uniquely innovative nor as much of an influence as its members like to make it out to be. If PHP is the kindergarden of programming languages, Ruby is the angsty teenager complaining about how nobody understands them and writing blog posts about their deep insights gained from flipping through Atlas Shrugged.
A major factor in popularizing it, as I claimed. Personally, I had never heard of it before DHH's 2006 RailsConf keynote. Could you point me to another web framework that had implemented it before 2006?
> Some of the syntax was influenced by CoffeeScript (nobody doubts that -- in fact, TC39 members have explicitly referenced it on more than one occasion) but the features are neither novel nor unique to Ruby.
Again, CoffeeScript was popularized by the Ruby community, as uptake increased greatly when it became a default in Rails. The syntax was heavily influenced by Ruby, which then found its way into ES.next.
> Front-end build tools
The Rails asset pipeline was actually listed as the inspiration for Brunch, the closest you can get to replicating its functionality in JavaScript. This went a long way towards popularizing the notion.
> I agree that CoffeeScript is the first one that gained major traction in the startup scene > although most teams seem to have realised that the drawbacks aren't really worth it (not just the transpilation...
Yes, and CoffeeScript first gained traction within Rails. You also seem to be discounting the obvious popularity of ES.next transpilers.
> The Ruby community is very vocal and self-important but it's neither as uniquely innovative nor as much of an influence as its members like to make it out to be. If PHP is the kindergarden of programming languages, Ruby is the angsty teenager complaining about how nobody understands them and writing blog posts about their deep insights gained from flipping through Atlas Shrugged.
This is rude, untrue, and unhelpful. Be civil. https://news.ycombinator.com/newsguidelines.html
I pointed out the major syntax additions of ES6 and to what extent they are based on Ruby or not.
> You also seem to be discounting the obvious popularity of ES.next transpilers.
I'm not. Babel and other "ES.next" transpilers are drastically different in spirit from CoffeeScript. With some exceptions (e.g. JSX and Flow type annotations) most of the syntax it adds to JS are either already part of the language and just not widely supported (i.e. ES2015) or experimental proposals for new language features intended to eventually land in a future JS spec.
CoffeeScript doesn't work because it requires you to learn a new language on top of JS. ES.next works because it's bleeding-edge JS (plus some speculative additions). The code you write for Babel today will likely run without transpilation in a JS environment a year or two from now.
This is a general trend in web technologies. CSS pre-compilers like Sass are being replaced or enriched by CSS "post-compilers" like postCSS (that consume vanilla bleeding edge CSS and spit out CSS that works today). JS transpiler languages like CoffeeScript are being replaced by ES2015 (and speculative ES.next) with compilers that translate the code to JS that works today (or yesterday, even -- Babel generally works fine with IE8/ES3 if you use the necessary shims and shams).
Your point is that Ruby's role to all of the developments you mention is essential and unique. I'm arguing it's not. By far.
The only remarkably unique thing about the Ruby community I keep noticing as an outside its rise and fall of the Brogrammer culture and the aftershock we're still experiencing to this day. But even that, I think, would have happened even if Ruby never existed.
The folks that have been quietly productive with CoffeeScript for years, and have and continue to make millions of dollars because of it, would likely disagree with you on that point.
> Your point is that Ruby's role to all of the developments you mention is essential and unique. I'm arguing it's not. By far.
> The only remarkably unique thing about the Ruby community I keep noticing as an outside its rise and fall of the Brogrammer culture and the aftershock we're still experiencing to this day. But even that, I think, would have happened even if Ruby never existed.
Well, you've failed to sway me on that (by far), and the clear chip on your shoulder you have regarding the Ruby community as a whole leads me to believe your vociferous arguments to the contrary might be motivated by something other than your desire to spread the truth.
I'm ranting. What ever gave you the idea either of us is talking about objective truths?
I wouldn't.
I will however agree that Rails probably should take most of the responsibility/blame for really bringing MVC to the forefront of web development