7

Show HN: Imba – I have spent 7 years creating a programming language for the web

 2 years ago
source link: https://news.ycombinator.com/item?id=28207662
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Show HN: Imba – I have spent 7 years creating a programming language for the web Show HN: Imba – I have spent 7 years creating a programming language for the web 269 points by somebee 4 hours ago | hide | past | favorite | 77 comments Hey all

My name is Sindre, and I am the CTO of Scrimba (YC S20). For the last 7 years, I have written all my web apps in a full-stack programming language called Imba. It compiles to JavaScript and its main goal is to make web developers more productive.

I just launched a major overhaul of Imba, so I wanted to share it here on HN, in case anyone are interested in learning more about it. It is very opinionated, so some of you might not like it, but I would love to hear anyones feedback regardless. Constructive criticism appreciated!

The backstory:

Imba initially started in 2012 as an effort to bring the elegance and conciseness of Ruby into the browser, and also because I felt that JavaScript and the DOM should be more tightly coupled together. Over the years, I have taken inspiration from React/JSX, and also Tailwind.

Since 2013, I have built several business-critical apps in Imba, so this is not a toy project or an academic exercise, it is extracted from a real project trying to solve real problems. Today, we are currently a small but passionate community of devs who use Imba all over the world.

The nitty-gritty details:

As mentioned, Imba compiles to JavaScript, and it works on both the frontend and backend. The quickest way to get a feeling of how it works is by checking out this video: https://www.youtube.com/watch?v=8XS5q9xhaMc

Alternatively, here is a list of the main benefits of the language:

* Clean syntax with built-in tags and inline styles

* Imba's Memoized DOM approach is *an order of magnitude* faster than Virtual DOMs (Vue, React). Learn more here: https://www.freecodecamp.org/news/the-virtual-dom-is-slow-me...

* Imba works with Node and the npm ecosystem, and integrates tightly with both JS and TypeScript

* Blazing-fast dev/build tools based on esbuild

Each of the benefits above are explained more thoroughly in our docs here, so please check it out if any of the above points spark your interest: https://imba.io

With this version I feel that I am very close to my vision for what Imba should be. In other words; it is finally ready for public consumption. I'd wholeheartedly advice you to look into it and give it a whirl if you are interested in web development :)

Hope you like it, and please share any feedback you might have in the comments!

PS! We're also hiring Imba developers at Scrimba - see https://jobs.scrimba.com/. We don't expect you to be a seasoned Imba developer, but we expect you to pick it up fast :)

I just want to compliment the OP on a very clear and comprehensive website at https://imba.io/. It clearly explains (by showing and telling) what Imba is, why I should care, how it works and how to get started. The floating demo applications even work well on mobile. Rare to see this level of polish for these things.
Really interesting project! I will definitely be trying it out today. One question—although you criticize some of the more common vdom benchmarks, I think it is still valuable to see where the dom updating strengths and weaknesses are in various approaches. Have you run any of the more standard frontend benchmarks on this and compared? I think it would be cool to see an entry for imba in the js-framework-benchmark table, especially considering your claim of low memory footprint.

https://github.com/krausest/js-framework-benchmark

Great work so far, I’m excited to give imba a spin.

s.gif
I will try to add v2 to that benchmark relatively soon - it is a lot faster than v1 and has a much lower memory footprint and faster initial load time :) Should probably combine it with a few pull requests to the benchmark itself - as I consider it pretty flawed (see another comment here).
This looks very cool, thanks for sharing!

I took a cursory look at the docs and it looks like async/await is pretty much directly analogous to how it works in JS, with the difference that you don't need to mark functions as async in order to use the await keyword. Does this mean that if you use await in any function then any other function calling it will have to be refactored to add an await keyword, just like you have to refactor any call sites in JS if you make a function async?

I remember seeing someone here on HN showcasing a language where they did the opposite, making it so that await is implicit, so calling fetch or anything async doesn't require an additional keyword, and functions don't need to be refactored just to sprinkle async/await everywhere. I'll see if I can find that language again, but it seems to me there may be some idea sharing between the two that could perhaps yield some amazing features...

s.gif
Asynchronous code can sometimes be difficult to write efficiently so having implicit awaits might help with avoiding accidentally made fire and forget calls. An interesting concept might be to explicitly call a function as asynchronous with a new keyword flipping the typical usage of ‘await’. I’d still advocate for the usage of ‘async’ in function signatures though as it helps when reasoning through an asynchronous code base.
s.gif
This is exactly how I remember it working in the language I mention (which, by the way, is called hyperscript[1].) The semantics where flipped such that you'd explicitly mark calls or functions as async, rather than await, if you wanted them to run asynchronously.

I run into subtle bugs all the time due to missing awaits, it's incredibly frustrating.

[1]: https://hyperscript.org/posts/2021-04-06-aysnc-transparency-...

s.gif
That pretty much describes Lua.
s.gif
Thanks for mentioning it, I don't know much about Lua. I found the language I was thinking of, it's called hyperscript. Here's an article about how async works in that language: https://hyperscript.org/posts/2021-04-06-aysnc-transparency-...
I’m sick of programming languages that use “fast typing” and “productiveness” as a selling point. There’s no selling point in being productive doing a counter in a few seconds, production scenarios are far more complex and very often all those new programming languages fall short to their promise. Btw I don’t want to be fast or productive, I want to write code that works decently and is great for other humans myself included
s.gif
It depends. If your work is to create a new counter app every day to support some specific, single usecase, in other words you write a lot of simple apps and not a single complex one, then it’s definitely a win for productivity.
Looks cool. I'm honestly curious as to why a lot of new web languages/frameworks are mixing logic and content in the same file again though. The distinction between HTML, JS and CSS always made perfect sense to me. Anyone care to enlighten me?
s.gif
This is exactly why I prefer Angular to React.

Our designer wouldn't have been able to deal with HTML markup within the JS files in React.

s.gif
Personally I've always been kind of confused by the common best practice of separating everything. React and Vue single file components made so much sense to me.

I guess if I were to rationalize my position, I'd say it's because I have a hard time finding related things when they're separate. If a button or "a" tag have a special click handler, I want to know when looking at it. If it just has classes, then I don't know if that are for style or if they're for behavior. I know there are some conventions out there where you prefix classes with "js-" etc, but if you just use "onclick" then it's obvious and you don't need a convention.

s.gif
It's fine if you have a few colors, but with 50+ lines of SASS/component I'd rather have them separately.

> I have a hard time finding related things when they're separate.

Store them in the same directory?

I agree on the events/business logic that they make sense to couple with the template code.

s.gif
> The distinction between HTML, JS and CSS always made perfect sense to me.

Really? HTML is already heavy on syntax, and the whole point of SGML-style angle-bracket markup is to invisibly structure text hierarchically and sneak in rendering properties or other "metadata" not rendered to the user, via attributes. In which universe, then, has it ever made sense to write

    <div style="color: red">
rather than
    <div color=red>
in a document representation language? Let alone today's CSS atrocities. Mind, I'm not talking about CSS' out-of-control layout model complexity, but inventing a new syntax (or a thousand microsyntaxes really) on top of already syntax-heavy markup.

If you think about it, CSS appears to have gotten these ninja super-powers because HTML was locked in a decade-long stagnation while W3C was busy with XML, RDF, and whatnot. Then again, in the last decade using <div>s for nearly everything was frowned upon, so with the precedent set in the decade before, CSS just had to re-order, re-place, re-arrange ad absurdum without any discernible mental discipline. Or, maybe the CSS WG people just couldn't stop.

The end effect is that CSS isn't approachable for even seasoned graphic artists let alone laymen; another effect being browser complexity resulting in monopolies.

A false separation-of-concerns narrative has ruined many languages and approaches (such as enterprise OOP); for the web it was particularly idiotic given it's founded on composable documents.

JS? Once it was out there, evolution of HTML and declarative UIs basically stalled because there wasn't anything you couldn't do using JS. Nevertheless, CSS had also grown into outlandish complexity. Basically, the "web stack" of today is what any standardization effort should've avoided.

s.gif
Not that I disagree that what we have today is a big mess but this sounds to me almost like the philosophy behind the old PHP version that everyone seems to hate. Personally I'd much rather have everything separated in a better HTML/CSS/JS than HTML+CSS+JS in one big pile. But I'm also not a fan of JavaScript at all, especially not of the hyped "one framework today, another tomorrow" that is JS development today. In my opinion in that area we are moving backwards very quickly.
s.gif
It's because of components.

Web app dev has started focusing on single, separate, reusable components instead of trying to design everything on the page at once.

Often, in these components, the HTML, CSS, and JS is still separated, but now (theoretically) you can plug that component in anywhere (even a different app) and, as long as you feed it the right data, it should just work.

s.gif
Hard to describe, but it feels like it makes much, much more sense. I think it's because the divide between html/css/js is supposed to be one of concerns, but in reality the concerns are interwoven in many ways, and leads to issues when using them at scale. None of the scaling issues I've faced in the past re-occurred when I used a framework that combined the languages into single files.
s.gif
I think eventually everyone just realized that so much of the styling is dependent on the element hierarchy that makes up the page that it’s pointless (and indeed painful) to separate your HTML from the component that uses it.

If you are actually using components, that isn’t much of an issue.

In a time when you’d be returning a whole document every single time, it might make sense to say ‘style this one document with this one stylesheet’, and even more so in a time when HTMl was still more or less semantic (e.g. an actual document).

s.gif
For web apps, you often want your content/HTML to dynamically render different elements depending on application state. Using a separate template file and having your logic plug into the template is often more complicated than just having your flow logic (if/else chains checking application state) return bits of relevant HTML/content inline.
s.gif
A feature usually consists of all three HTML/CSS/JS.

So, if you split by technology, you don't have the code belonging to one feature in one place.

s.gif
Separation only works for so-called leaf components: buttons, links, tabs etc. that can actually be reused.

And even then you will definitely run into issues such as "in this particular case this particular tab will look like this".

While the web was mostly leaf components (text, articles, images, links) this separation kinda worked. The moment you move into app territory, there are not that many things that are reusable and benefit from separation, because your UI is directly dependent on business logic and vice versa. And because every screen in your app is a unique view into a unique part of your functionality.

s.gif
The distinction makes sense on documents but it starts to break on apps. Javascript depends on HTML and HTML is generated by JS.
Quick question - how does the memoized DOM compare with no-virtual-dom-at-all approach of something like Svelte?
s.gif
https://krausest.github.io/js-framework-benchmark/2020/table...

This lets you choose from multiple frameworks - comparing svelte against a few react variations, what I saw was that svelte was always fastest, but usually by a factor less than 2 (any react was 1.x times slower than the svelte).

The imba vs react numbers (from the article at https://www.freecodecamp.org/news/the-virtual-dom-is-slow-me...) shows a 30-40x speed difference.

s.gif
Tbh, I think the js-framework-benchmark is flawed. It mostly tests the performance of the browser. I should write a whole blog post about this. Just as an example, all the table benchmarks uses a table with non-fixed width, which results in a full repaint AND layout of the whole table+page whenever a cell changes. If you change the table to a fixed width (as all real tables are) the relative difference between the frameworks increase by a factor of 5 or more.

And when you benchmark the speed of creating 10000 dom elements in an instant, less than 5% of the time should really be spent inside the framework one is supposed to test.

I stand by my claim in the mentioned article that tiny changes to a larger dom tree is a far better indicator of real world performance than anything else. Here Imba is really orders of magnitudes faster than react.

The last time I tested it, Imba was more than 10x faster than Svelte as well, but I'm not proficient enough in Svelte to claim that as a fact, and I have tremendous respect for Rich Harris and everything he's done with Svelte and other libraries.

s.gif
Flawed in what sense? I don't doubt that there are some conceptual drawbacks, and this only benchmarked chrome, not other browsers. I do think there's some utility in relative comparisons that have a standard/fixed baseline, as it would still seem to show what overhead a framework/library brings to the table.

FWIW, my initial impression of imba is that it's very impressive. I do think you rightly point out that, at this point, it may still be hard to leave larger ecosystems of react/vue/etc. DOM/UI speed of the project's JS toolkit generally has not been any meaningful impact in the projects I've worked on in the last several years - the data size and audience and app space just don't really call for it. However... as my needs change, imba will be something I'll revisit. Thank you.

That's a very tight integration with JS&TS! Are you compiling into TS and then to JS? Or is it more of a decoupled process that was set up for the type-checking (like how tsconfig and babel works together)? When I was trying out ReasonML a few years back (and being unfamiliar with OCaml) I ran into some problems with bridging across types.

I checked out https://github.com/imba/typescript-imba-plugin for a bit and I'm still quite lost. Love to learn more!

Also, what is the cross-file refactorings in the tooling? Thanks!

s.gif
Yeah, the typescript-imba-plugin does quite a lot of magic and might be a little rough to get into.

We essentially do the type-checking by compiling the files to js with jsdoc annotations, and for some features we also generate `.d.ts` files (see https://dev.to/somebee/global-type-augmentations-with-automa...). There is still a lot of work to be done on the integration. There are bugs and missing featyres, and the type-checking only happens in the tooling atm. The compiler could not care less about your types.

Since it is developed as a ts language plugin, references to imba files (like goto definition etc) works from ts/js files (you can include imba files in js/ts), and renaming methods / files works across all ts/js/imba files in your project.

I wonder if there are plans for an imba course on scrimba. I think it would be a fun concept and could be a used as a free introductory course (both familiarizing more of the world with the language and the scrimba platform)
s.gif
Yes, there are plans for an imba course on scrimba! It is almost comical, but scrimba was originally created with the sole purpose of teaching people Imba. Here we are, 4 years later, finally preparing to make a course :D
s.gif
Yep, we will be making both individual scrims to use as examples and tutorial about building something more comprehensive.
I am glad you persevered. I’ve been working on a language for 3 years now and sometimes I lose faith. It’s good to know that sometimes, projects can be finished (or at least shipped ;)
You call it "full-stack" and mention memoized DOM, which makes it sound like it's not only a language but also a framework.

Is there a clear separation between those two parts? Could someone take just the language without the framework and use it for something that's not web related?

s.gif
You can definitely use 'just the language' part. I'm using it daily for scripting, and we've written a lot of apis and libraries at Scrimba that does not utilize any of the framework-ish features of the language. But to make the tags and styling work really well it (imho) has to be thought of at the language-level.
Looks great! I’ll definitely be checking this out for my web work. One thing I see- and only mention because the rest of the product seems like it has an eye for detail- the “we are hiring” link and paint component on imba.io have minor layout issues on iOS Safari on iPhone 12 Max Pro. I haven’t tried other devices, but mobile responsiveness is one thing I look at when evaluating tools like this.
is there any particular reason why there doesn’t seem to be built-in type-checking system? i know it still seems to be a “personal preference” whether to check one’s types, but i wonder if any thought was given to including it?
s.gif
There is built-in type-checking, but currently only via the tooling. It integrates with TS as a language service plugin (https://github.com/Microsoft/TypeScript/wiki/Writing-a-Langu...) so you get great warnings/errors, type inference and much more. To define standalone types or interfaces you still need to use `.d.ts` files, but that may change in the future :)
s.gif
that is to say, the types are not part of the syntax in any way?
s.gif
You can typeset variables, parameters etc (ie. see the code in https://dev.to/somebee/global-type-augmentations-with-automa...). But declaring standalone types is still done in `.d.ts` files. Imho, the type inference in ts/js is getting so good that I very rarely need to declare any explicit types in my own projects.
s.gif
Interesting.

I had the impression "tightly coupled with TS" would mean type checking.

That's sad.

This looks pretty good, but it would be better if you compared the performance and rendering approach to Svelte instead of React and Vue. It's well known that virtual DOMs are not good for performance.
Wow, congrats. It looks great, need to try it. The video gave me the same feeling I had when I watched the original rails demo video [1].

1. https://www.youtube.com/watch?v=Gzj723LkRJY

Would it be possible with this to just apply tailwind css classes instead of learning this built in style syntax?
s.gif
Sure, you can apply tailwind classes like `<div.w-32.h-32.rounded-full>` etc, but I'd definitely recommend using the built in styling as it is much more powerful (value interpolation, flexible modifiers etc).
s.gif
Great! I am interested in trying out the language and learning more but there would be a lot less friction and mental confusion on my side if I can get started and apply tailwind classes and use something I'm familiar with.
Hey there! I think it is really cool language. You can basically get started in minutes.

Does imba also have native app framework too?

s.gif
No, not right now. The current version of tags is relatively tightly coupled with the DOM for maximum performance. It should be possible to create a bridge like react-native but it hasn't been an area of focus thus far!
This is very cool. It seems like the perfect language for making web components. Do you have a "compile as component" mode to output components or component-like packages (like Angular Elements)?
Always impressed by what you are able to achieve Sindre.
Imba looks great! Now that v2 is out, what would you say are your priorities regarding Imba? Is there a roadmap somewhere?
is there direct support for websockets? channels or something?
Reminds me of my LiveScript days.

I'm impressed!

Looks great! Congrats for being a YC alumni. One day myself perhaps...
Looks great!

From a first look, I love the dimension types and the tags which compile down to native web components.

Hope good things for this.

Wow you are clearly a genius. The syntax looks beautiful! This is great. I don't want to use it (the best tool for the job for me is one that fits my own mental models, my own mind, and this is not it) but you are a genius.

Also -- wow those Nordics are super productive programmers/coders/developers/open-sorcerers (Sindre Aarsaether & Sindre Sorhus & Linus Torvalds & ...<please insert other names below to educate me>...) -- could it maybe have something to do with: The low GNI, the high HDI and the great weather for coding? (cold, blistery, bleak, focused, electrons-and-light universe is only outlet in a desolate landscape)? I have been to Oslo. The architecture is great.

PS - I use my own memoized DOM with minimal/granular updates in my own quirky framework (https://github.com/i5ik/vanillaview)

PPS - BTW memoized DOM is a great term of art. I perhaps shall be using it from now.

CONGRATULATIONS, SIR!

PPPS - Also what you are doing with Scrimba is so incredible. And GOOD. You are such a fuqing genius. Wow!

One thing that irks me about Javascript is "const". I think it should have been called "con". "var", "let", "con".

So the first thing I did here is look up the docs and see how variables are declared. Aaarghh.. "let" and "const" again :)

s.gif
I've thought about this a lot. I considered "con" for constants. I don't hate it. It also works as a double entendre-- "con" in Spanish means "with". So the following code could be read as "with name equal to Brad".
  con name = 'Brad'
I can't help but feel that it's somewhat jarring though.

If I had my druthers, I think I would choose "var" and "def" to declare mutable and immutable variables, respectively.

  def PI = 3.1
  def degreesToRadians = degrees => degrees * (PI / 180)

  var degrees = 180
  var radians = degreesToRadians(degrees)
Edit: After thinking about it some more, I think I prefer "const" over "con", but "def" over both.
s.gif
You are obviously right.

The 'const' nomenclature is an abomination before science and human progress. However, given the prior art, I don't think we can hold it against a new/emerging language.

Anders, help us! Do the right thing. You are the only one who can.

(Of course, 'const' could be grandfathered and still work forever. Right-minded people, please upvote this obviously-right person at least back to a neutral #000.)

s.gif
Why do you think this?

"const" seems clearer to me. "con" seems very open to misinterpretation: could mean many things.

Are there any advantages to "con" over "const"?

s.gif
My guess is the OP dislikes the difference in keyword length.
s.gif
Why does const irk you? const sounds a lot clearer than con. Is that your primary criteria for picking a language? ;)
s.gif
I think it has three reasons:

The more often a construct is used in a language, the shorter I like it to be.

It groups variable definitions mentally by having them all the same length if they are "var", "let" and "con".

It would often make the code look more uniform which is more beautiful in my eyes. Example:

https://github.com/facebook/react/blob/cae635054e17a6f107a39...

I would prefer the lines 226 and 227 to start with "con" and "let". It would make the code visually more appealing to me.

s.gif
As far as code being visually appealing, for me those two lines are the least of that code’s troubles.

I’m sympathetic to wanting code to have good aesthetics. If I was writing those lines I probably would have daydreamed for 5 minutes thinking of new names for map and record so that the equal signs would line up.

s.gif
I've never used a language with a 'cons' keyword, but nevertheless that's what I'd assume your 'con' was, if you didn't tell me otherwise.

I'm no particular JS fan, but 'const' is much clearer, it's a complete syllable, just like 'var' or 'func'. Yes 'fun' is used, but I think that's awkward for the same reason.

s.gif
Tbh, var is actually deprecated since v1, so any mention of var in the docs is a mistake. Are there any other languages using 'con' for constants?
s.gif
Good idea IMO. That feature should be pretty easy to add (famous last words).
s.gif
Is the difference in length bothering you? In that case I find that let for immutable and var for mutable is pretty good, although for a language that's lose to JS that might not be a good idea. Maybe let for mutable like in JS, and val for immutable? (inspired by Scala).
s.gif
Personally I don’t use any languages with reserved words
s.gif
that limits the number of languages to a handful. like brainfuck and similar ones. doesn't it?
s.gif
APL cheats by making everything a symbol.
s.gif
Lisps don't have reserved words, generally.
s.gif
Depends on what you mean by "reserved word". In Common Lisp, you can define your own cons and defun, provided that you're not attempting to mutate the respective symbols from the COMMON-LISP package. That can be achieved by either defining your own cons and defun and shadowing the cons and defun from the COMMON-LISP package (typically for function or macro bindings), or just straight up using cons and defun from the COMMON-LISP package in "legal" ways - for example (let ((cons 1) (defun 2)) (list cons defun)) is legal and evaluates as '(1 2) since using those two symbols as names for lexical variables doesn't break the running Lisp in any way. In the former case (of defining your own functions/macros accessed as "unqualified" cons or defun from your own code) it's up to you if you consider cons and defun to be "reserved words" based on their package or not (packages for reserved words being something that languages explicitly recognizing the concept of a reserved word don't seem to have, so it's not clear how this should qualify). In Scheme, a Lisp-1, it's kind of free-for-all, especially in R5RS where you don't even have to bother with hiding standard bindings.
s.gif Applications are open for YC Winter 2022
Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search:

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK