179 comments

[ 3.4 ms ] story [ 210 ms ] thread
(comment deleted)
I don't think of react as a language, but rather a virtual DOM + JSX.

This looks like a nice modern syntax which is both an ES6 focused minimal JS (removing unnecessary tokens) with HTML building included.

It's confusing they made a whole nice language that doesn't speak about react VDOM diffing which .. was the whole point right ?
Hi. We actually do a different kind of diffing - which turns out to be substantially faster than React: http://somebee.github.io/todomvc-render-benchmark/index.html. The language has just been released, it is still very lacking when it comes to documentation. Working on it :)
Fair enough, I guess you have other more important things to do then.
Can you give some details about Imba's diffing?
What part of the diffing?

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.

So this is basically coffeescript. Where's the react part?
Scroll down to 'Tags'.
"if Ruby and React had an indentation based lovechild, what would it look like?"

Let me guess!... CoffeeScript?

yeah, just add the jsx to CoffeeScript :D
Imba was actually forked from CoffeeScript three years ago. After the fork there's been a bunch changes, both in terms of adding tags, but also when it comes to the object model and variable scope.

- 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();
      });
    };
- Implicit calling: `foo.bar` calls `foo.bar()` and `foo.bar = 123` calls `foo.setBar(123)`

Wuhh. Why wouldn't you use JS defineProperty here?

There's one historic reason (it wasn't widely available when Imba was started). Another reason is performance: the last time we benchmarked this `defineProperty` was slower than regular function calls. Maybe it's improved now.

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.
Re implicit calling: what would you write if you wanted to access `foo.bar` as a function instead of calling it?
I'm also wondering this. It looks like a huge design error.
foo:bar is property access.
(comment deleted)
Why is Imba any better than Coffeescript? It looks like it does nearly the same thing...
I lot of these things are basically irrelevant if you use ES6/7.
Most of it's good, just a cleaner JS, but it'd be better to drop the classes and lambda-type short function syntax in favour of ES6 classes and arrow functions.
Are brackets and semicolons now optional in ES6/7?
Semicolons have always been optional. Brackets are only used for array literals (oh and destructuring assignment) as far as I know (and are required).
really love the design, and how it shows the whole language on the frontpage.
This is good! Now take away all the unnecessary references to that pile of junk that is ruby and it'll be great.
I don't know that I agree with that... a lot of the syntax definitely burrows from Ruby, but then again so does CoffeeScript... this actually looks a lot like CoffeeScript with embedded razor templating.

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.

This tool is forked from Coffeescript, which is deliberately designed to resemble Ruby. There's a good reason for that – some aspects of Ruby's syntax are well-loved.

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.

> some aspects of Ruby's syntax are well-loved.

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.

> By Ruby programmers.

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.

By Ruby programmers.

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.

yeah sure - I was a bit troll-ish in the language. Let me elaborate. Imba is a spin-off of javascript intended for front-end use whose syntax is a mix of coffeescript, jsx and python as well Ruby imho; that said, please name a single use case in which Ruby will be without a doubt the #1 language for performance, scalability and all the other aspects involved in maintaining a business (including availability of programmers). Ruby is only second to PHP, which is just unreedemable (I'm even certified on it... http://www.zend.com/en/yellow-pages/ZEND005898 so don't think I'd refrain from criticizing languages I know, even very well).
(comment deleted)
(comment deleted)
Thank you for not saying "transpile".
Yup. "Transpile" is "compile" for those who're too young to ever have worked with a compiled language.
I suppose the idea is that 'compile' implies a low-level target whereas 'transpile' suggests translating to another high-level language. I can see some sense in making this distinction.
In the larger linguistics world you have a distinction between "translation" (conversion between languages) and "transliteration" (conversion between forms of a language; cursive writing versus typing versus speech, for instance). I remember this being a particularly important distinction in learning American Sign Language (ASL) because the vocabulary is roughly English-ish it is very easy to transliterate and try to say in ASL an English sentence "as is" without meaningful changes, but just with dealing with the differences between, say, English and Spanish, to speak ASL properly you need to actually translate to more idiomatic forms and abstractions. This is extremely important to ASL not just from a "speak better ASL" standpoint but also because it comes out of a foundational, cultural imperative: ASL was not seen as "a real language" until it proven to some linguists that it validly needed translation, was not just a transliteration of English but in fact a language with its own idioms and grammar requiring translation. This disagreement is so fundamental to ASL also because there was so much pressure from people to "speak real English" rather than develop their own language. There is a transliteration-focused "alternative" to ASL that includes all of the useless English grammar and stutter words like "the" that ASL handles grammatically different, and ASL had to prove its existence against it and also to prove that it was better and also to prove that ASL speakers could still read/write English to work with the rest of the English-speaking country when their native language was grammatically different enough to require translation... It's an interesting cultural battle to read about.

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.

Is there more information about how the 'very efficient rendering' part works?
There's two parts of the "very efficient rendering":

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.

Disclaimer: I've been following the development of Imba while it's been a private project (for six years now). Lately I've been helping out fixing bugs and improving smaller parts of the language.

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`.

I would really like to see React do something like this as a shortcut to having to do map. It would be SO helpful.
The benefit of JSX is its syntactical simplicity. Lots of beginners seem to think JSX adds all kinds of language features but in reality most of them are unrelated to JSX and either part of ES6 or experimental features of ES7.

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)`.

The React API would be much nicer if it could use Javascript generators.
You can do that right now with CoffeeScript+React and it looks almost identical:

    {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}
Yup, that looks pretty good.

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.

Can't really comment re the language (the tags as part of the language is very nice, I agree), but it's been in development for 6 years and there are no docs? If it were just a Coffeescript fork & just basically a matter of syntax, then maybe fair enough (but LiveScript & CS both have relatively extensive docs), but this project has much grander claims (ie that it's also a high-level framework competitor) + a grand total of a single page of basic info + no particularly useful source code comments. Sorry to dis a project you're connected to, it just doesn't look good in that respect
Unfortunately we were too busy building actual applications. In total it probably sums up to a number in the magnitude of 100k LoC.

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.

You should check out https://readme.io for getting started on docs – they offer the platform free to open source projects.
I will do! I didn't mean to be too down on it, just slightly disgruntled when I tried to locate semi-detailed docs. Looking forward, and given you've been building real stuff in it, maybe worth writing up how you've used it, how how the features have been useful, how projects have been structured, how they fit into workflow etc.?
Can you comment on why the project was kept private? Don't mean that as an implicit criticism: I'm just curious.
As someone who has been developing using Javascript for 10 years and has seen many frameworks comes and go (including authoring one), this looks refreshingly good on first impressions. Far better than coffeescript or React. Congrats!

Plus, I love the fact that the syntax looks Pythonic :)

Anybody know the color scheme for the code on this page?
Looks like Twilight (which started life with Textmate, but has taken off all over since), or a variation thereupon.
So... I don't understand if you're supposed to use this with react, or instead of react?

If the answer is "instead," is it a language and a view framework?

This isn't a competitor to react; its a competitor to ES6/typescript/coffeescript.

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

Imba includes syntax for tags (scroll down to "Tags"), virtual DOM diffing, event handling (with touch support). Yes, React is not a language in itself, but there's quite big overlap in what Imba does and what React+JSX does.

You build UI components like this:

    tag event < div
      def render
        <self>
          <h1> event.title
          <p> "Happening on {event.dateString}"
No.

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.

I can only conclude that you're so focused on aggressively dismissing this person's work, in the typical HN fashion, that you didn't actually read the comment you responded to, or any of their other responses throughout this thread.

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.

judofyr's comment that you're quoting was posted after shadowmint's.
TFA however, which has examples of that stuff, was posted before shadowmint's.

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.

The second quote, maybe, but the first comes directly from the comment shadowmint is responding to here.
Its great how you can edit comments isn't it? Both quotes were edited.

Still... I suppose that my original post remains the top here says something. Cant reedit something with no parent. too bad. ;)

Sure, but it's in the damned article.
just so i understand this correctly - you also handle diffing & patching the virtual dom? If so, a few questions:

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?

Any plans for SVG support? I'm getting errors when using <svg>, but maybe there's some way to make it work?
I find the structure of an Imba app rather intriguing; the view+rendering (i.e. tags) almost looks like an upgraded HTML/HAML (possibly akin to EnyoJS).

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.

How does it handle data binding?
It looks similar to React's one-way data flow - that render method produces the whole app view, and refers to all the necessary variables. When an event occurs [e.g. the user types text to add and hits enter]:

- 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.

I guess the title should be JS/React
My first thought as well, even though I know little except the marketing about React. It's like if someone said "Foo: a new competitor to Rails", or "Bar: a new competitor to Vim".

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.

Mithril author here.

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.

> 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.

Hi, just wanted to clarify I'm not trying to badmouth, just pointing some things that weren't clear to me (as someone who would be qualified to evaluate the quality of a React-like framework). Lack of docs aside, it does look like a nice project :)

> 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.

> can't tell if it's actual speed or "cheating"

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.

(comment deleted)
See comment: https://news.ycombinator.com/item?id=10095990. Thanks for taking the time to looking through the benchmark. I think you are misinterpreting things. Yes we do caching, and yes IF your app created a million tasks every second you would need to manually dereference them at some point. But you could change the caching (as mentioned in the comment) to never cache additional tags (instead of disabling all caching - which would be like going into the code of Mithril and React and remove all checks in the virtual dom).

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.

> 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.

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.

Thanks :)

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)

>This isn't a competitor to react; its a competitor to ES6/typescript/coffeescript.

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?

I actually think this looks really good, but 3 things:

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.

1. Because the semantics are quite different. See my other post.

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.

People also know CSS query selectors...

    <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.
Imba supports the syntax for IDs and classes:

    <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).
After reading more, I agree with you on 1 and 2.

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.

I can't speak to #1 and 2, but for #3, one of the criticisms of CoffeeScript has been that defining local variables and modifying variables from an outer scope have the same syntax. I.e., if I see `foo = 1` in a piece of code, I don't know if it's creating a local variable called foo or modifying a variable called foo from a containing scope -- the only way to tell is to scan all the containing scopes for a variable called foo. Even worse, let's say a piece of code had an inner function that declared a variable foo, but I then declare a variable called foo in an outer scope. That inner statement now silently switches from declaration to modification. I suspect this is why they force the use of `var` for declaration -- it disambiguates the two cases
Contrariwise, implicit creation of local variables is my biggest pet-peeve with languages like Python, so ymmv.
#3. Python did the mistake of not having a var keyword. When you have nested closures you don't know if you are assigning a variable in the outer scope or the inner. You have to use hacks like creating an array of length 1 in the outer scope if you want to modify it in the inner scope otherwise you create new variables in the inner scope each time you try to make an assignment.

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.

I have to admit I was really not excited to see 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?
CoffeeScript (which this is forked from) has some parts like this that I strongly dislike, such as using the unless keyword after an action. For example:

    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)

To play devil's advocate, when using Python's ternary operator like this:

    something() if False else y
The `something` function is never called.
The unless keyword is very useful for when you're testing an exit condition, e.g., return unless...
That's not specific to 'unless' – it's the general postcondition style that's is derived from Ruby. Indeed, for single-line if statement bodies in Ruby, it's the recommended style.

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.
That's not really the part of unless that bothers me - it's the order. Why not do:

    if !record.persisted? && !record.invalid?
        save!
or:

    unless record.persisted? || record.invalid?
        save!
The behavior here, if it comes from Ruby, almost definitely has it's legacy in Perl, so you can look to Perl for justifications. The main justification is likely to be that's a natural construct of how we think and communicate, so why not allow us to express ourselves that way?

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?

I guess it's generally just that it's regarded as fairly idiomatic Ruby. bbatsov's popular style guide, for example (https://github.com/bbatsov/ruby-style-guide#if-as-a-modifier):

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!

Well just don't use the unless keyword then. I've used CS for years and I don't use it.
Well sure. But I live in a weird world where I sometimes have to work with code other people wrote, as well as my own.
As a Perl programmer, I'm often using contructs like that, and I think they have a place, but you should restrain yourself from using them in places where they can easily be misunderstood.

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.
Technically, the language has patterns (e.g. identifiers) too.

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).

This comes directly from Ruby via Coffeescript.

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.

Does Ruby allow the value of the if statement to be used as the RHS of an assignment? That's surprising. In Perl, which I assume they got that from (it's a fairly safe bet, Ruby is heavily Perl influenced), postconditionals are not allowed to be used as a statement, they are statement modifiers. You can do this:

  $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).
Ah, that's interesting – they become expression modifiers instead.

  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
And that's different than in Perl, where they aren't statement modifiers (I slightly misspoke), they really are just rearranged into single statement if blocks. That is, if the postconditional is false, the statement is not executed at all.

  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.
I think Ruby got it from PERL... And I'm not sure if PERL was the first language to use these, either.

EDIT: of course, there's Smalltalk, where postfix conditionals and loops are the only form available. Maybe Ruby got inspired by those.

Algol 60 had conditional expressions. Pretty much every functional language and LISP has them. They've also been in use in mathematics for longer than computers have been around.
Loops as expressions return an array as the value, the page says, but the JS code on the right doesn't seem to show this happening. Which is right? Or does the compiler notice in these cases that the value is not used, and not produce it?
> Imba is a new programming language for the web that compiles to performant and readable JavaScript.

More like, "Imba is a new syntactic 'skin', which transliterates to JavasScript."

Again that mistake with ASI - I wonder how much people like stepping on the same rake.
Why do people keep throwing around the idea that "X tool is Y times faster than React?" Last I checked no one was claiming React is super fast and I don't know anyone who uses it for its speed. It just seems like such a strange thing. It's like building a new car and claiming it's 100 times faster than riding a horse.
Virtual DOMs were pretty much invented while searching for a way to get higher rendering speeds. Just google "virtual dom speed".
If only horses existed, and you were the first to make a car, would it not be an apt comparison? With performance at 100k renderings per second you don't need to care about keeping the view in sync anymore?
Fun fact: "imba" means "sing" in Swahili, a language spoken in East Africa (Tanzania, Kenya, and to some extent Uganda, Rwanda, Burundi, Malawi, and DR Congo).
Interesting, great work. As someone who's never been able to get on board with JavaScripts syntax, this looks like a viable alternative to CoffeeScript.

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