Show HN: Joy – a Go to JavaScript compiler
mat.tm
mat.tm
While this may not seem like a big issue, having to conceptually know what works and what doesn't is mental overhead, so reducing that overhead by making it super prominent would be great for me. Thanks!
This looks really cool btw, once I have a better idea on the completeness of this, I'll definitely try it with React! It's the one thing I failed with GopherJS on, React integration was difficult to keep performant. I'm excited :)
I'll be here to answer any questions you might have!
I am not very familiar with Go and am only barely passable at Javascript - but aren't these the wrong way round?
So, how is this different?
EDIT: asked in the Golang slack. Will update when I find out the answer.
> GopherJS emulates a 32-bit environment. This means that int, uint and uintptr have a precision of 32 bits. However, the explicit 64-bit integer types int64 and uint64 are supported. The GOARCH value of GopherJS is "js".
Joy doesn't seem to be:
> [Joy ships] a minimal runtime only when it's needed
> Most existing Go code does not yet compile to Javascript. This is because most of the standard library still needs to be translated to Javascript. This will be a focus of the 2.0 release. Signup for the mailing list to follow along with the progress.
This has some obvious consequences in how they differ. For example, if I look at [0][1], GopherJS results in a huge amount of code bloat because it includes a translation of the Go runtime. A basic example 33 LOC grows to 44 LOC on its own, but with the GopherJS environment that becomes:
> 1470 LOC and 45kb, uncompressed and unminified. The bulk of which is the builtin library. It will only compile what it needs to. So if you declare types that are never used, they won't show up in the resulting code. This goes for core packages too. If I change that code so it requires "fmt", the result explodes to 12845 LOC and 624kb ("fmt" imports a LOT of stuff).
(In GopherJS' defense, minification slims it down to 21kb, and the example probably is missing a production code compiler flag)
The examples on the Joy webpage look a lot more minification-friendly and easier to integrate with other JavaScript.
[0] http://legacytotheedge.blogspot.se/2014/03/gopherjs-go-to-ja...
As a counterexample -- it is not possible to have a 33 LOC example that uses goroutines to only expand to 44 LOC. GopherJS goes to extremes to make sure that your Go code works as expected in the browser.
I'll be back on this thread tomorrow to answer any lingering questions. Feel free to open an issue on github with any additional questions or ping me at twitter.com/@mattmueller.
Thanks everyone and good night!
That's a known GPL quirk, and other GPL-licensed compilers like GCC use a separate variant of GPL to avoid that collision.
You can see how GNU Bison does it: https://git.savannah.gnu.org/cgit/bison.git/tree/src/parse-g... since they put fragments of Bison code to the final generate source file. That's exactly what Joy does to generate JavaScript, so you should put similar notice to the repository.
Also, LICENCE file is not there.
My company has a few libraries (including a language parser/compiler) currently written in Go, and we have a need for the exact same functionality in the browser and in other places (e.g., Node.js apps). Rather than port everything to JS and have two codebases to maintain, we tried translating with GopherJS, which seemed promising at first. But the emitted code was enormous, and it pulled in parts of the standard library that couldn't be transpiled. (Our code had limited dependencies, but our main problem was the "fmt" package, which, if I remember correctly, is somewhat special and not something you can just omit.) In the end, it was too much work for a small company with our limited resources.
Is Joy intended to serve this purpose?
I've created an issue for your purpose: https://github.com/matthewmueller/joy/issues/63
I definitely want to take the stdlib slow and not overdo it. If we can't make it work well in JS, we'll probably just leave it out.
I'm pretty sure Joy is a kind of "silver bullet" for programming, in the sense that, as "software is eating the world", Joy will eat software.
I have some Jupyter Notebooks here (also in HTML and md formats; md is good for looking at the 'books in situ on github): https://github.com/calroc/joypy/tree/master/docs
RIP.
"Hello. Tech support? This is Manfred von Thun. My computer is not working."
"OK, no problem, do you have a PC or a Mac?"
"Neither."
<Pause>
"Neither?"
"Yes. Neither."
"Ok, what do you have, then?"
"I have a terminal which connects to the mainframe."
<Pause>
"OK, I'll be right over."
Sure enough, he gets there and there's some godforsaken yellowing text-only terminal thing with a wire plugged into some weird port he'd never seen before, presumably wending its way into the bowels of the university to some long-lost, dusty piece of big iron from computing's distant past.
My mate was incredulous. "So what do you do with this, exactly?"
"I write papers, I write programs, I make web pages."
"Web pages!?"
"Yes, web pages. But I don't believe in graphics."
In spite of his protestations about GUIs, he was eventually given a brand spanking new eMac (this was around about the time he was creating Joy). Once he saw Terminal.app, he no longer seemed particularly concerned.
I remember using vi in typesetting a paper with LaTeX before print previewing a DVI on one of the PC or Mac machines.
I remember a mixture of VMS, Ultrix and I think SunOS. A monochrome screen with curses to do your email, browse gopher and text-only web, compile and run programs (in Manfred's case) and log in from any terminal on campus. There were a couple of monochrome Xterms in the computer centre. But desktop computers had obviously taken over by your friend's era.
The tribute pages below provide more insights from others.
I was studying in the mathematics department at the time, which was on the other side of the campus from the philosophy department. But there was considerable overlap between pure maths and formal logic. Godel's incompleteness theorem was one of the topics we proved and provided a good theoretical foundation for higher order logic.
http://hosted.verticalresponse.com/291390/14a69b5ba4/test/te... https://respectance.com/tribute/manfred-von-thun/
It's pretty obscure, but I have high hopes for the language. It has some amazing qualities.
I thought about it a little more and I don't think there should be an issue. This project is a compiler, not a language – Go is the language. It's analogous to Javascript and Babel.
Yeah, I don't actually think it will be a problem in practice. (And anyway I refer to my interpreter as "Joypy".)
It was sort of a knee-jerk reaction to seeing the name.
BTW, awesome idea and project! I hope it gets traction (at least until WASM "hits", eh?)
I absolutely love the idea of transpiling other languages to readable (and therefore, debuggable and maintainable) Javascript.
Kudos and I'll be watching this project.
WASM is on the radar though: https://mat.tm/joy/#faq-webassembly
I almost used this software, but I'm going to have to go through the code before I do now.
error downloading headless chrome: error making directory: mkdir /Users/matt
I'm not really clear on why it would need to create a folder under Users on Mac.I am looking forward to giving it a try, though.
Will fix it in the morning but I need to sleep now. Zzzz...
Thanks for the kind words and please try it again tomorrow :-)
I could be completely missing something, but mat.tm is down.
Thanks, but for type system we already have type script. Secondly, the post powerful Golang feature which is you know co-routines can't be translated to javascript
Actually to my surprise, goroutines and channels can be modeled quite well in Javascript! Right now the compiler uses async/await but for 1.0, I think it's possible to compile it down to ES3.
I'm wondering if Promises are the right way to compile goroutines though. Promises don't run in parallel, and they actually do block; they don't defer to the event loop. I wonder if compiling to web workers would be possible though...
Javascript doesn't have threads, so true coroutines not really possible (w/o webworkers). If you lock up the event loop in one of Joy's goroutines, the other's won't proceed.
This limitation doesn't mean that we can't use the CSP concurrency model in an awesome way in Javascript. If you search NPM for csp or channel, you'll find some good examples.
For the Go programs I've come across using goroutines, calling an async function like this (async () => {})() is a good enough approximation for frontend development.
You may lose out on true parallelism and better error handling, but that's the JS environment we're targeting.
A coroutine is not a thread and an implementation of coroutines does not (necessarily) depend on threads. Goroutines can also run on a single thread.
FYI GopherJS (the original Go -> JavaScript transpiler) has full support for goroutines. So "can't be translated to javascript" isn't quite right.
The post describes how the author has used, and liked, TypeScript but still wants Go's type system.
> Secondly, the post powerful Golang feature which is you know co-routines can't be translated to javascript
Why can't it be translated? A 5-second search of the git repo found this test case specifically checking whether goroutines are translated correctly:
https://github.com/matthewmueller/joy/blob/bb4ad647369331b55...
(Also, it wouldn't surprise me if the majority of goroutines in practice were I/O heavy and not computationally heavy.)
How are the two threads communicating? Via a channel? Why can't you schedule when a value is pushed onto a channel? Why do you need preemption in this situation?
(Maybe I'm wrong and Go handles this smoothly?)
Or, more specifically, that if you have N goroutines that consist of infinite loops of pure computation (or really, anything that doesn't involve receiving from a channel), and at least one other goroutine that's receiving from a channel, your runtime needs to generate at least N+1 OS threads or your last goroutine will never get scheduled.
https://github.com/golang/go/issues/11462 seems to be saying the same thing (by setting GOMAXPROCS to 1).
1) async/await are not supported in ES5, so after translating code from Go to JS I would also need to babelize it!
2) parallelism is not preserved
3) maybe it's just me, but in fat client apps it's all about event handling and data flow, co-rotines are not very useful there. But in Golang it's the most powerful feature ever(IMHO)
2) Parallelism isn't guaranteed by goroutines anyways, and this is targeted towards building new apps more than it is reusing existing Go code, so it shouldn't really be that much of an issue. Most web apps/SPAs have no need for parallelism.
"Actually to my surprise, goroutines and channels can be modeled quite well in Javascript! Right now the compiler uses async/await but for 1.0, I think it's possible to compile it down to ES3."
I would suggest that coroutines can solve event handling problems quite nicely. This is not exactly a novel idea either. There are toolkits in the wild that are designed to work exactly like that. From what I understand, there hasn't been any serious exploration of building UIs in Go, but I think its native coroutine/channel support has the potential to provide some interesting ways to handle events that are generally shied away from in languages where coroutines are not as easily used.
This is the key word. It is never guaranteed, so apps don't require it.