Show HN: Joy – a Go to JavaScript compiler

(mat.tm)

201 points | by matthewmueller 2338 days ago

16 comments

  • notheguyouthink 2338 days ago
    Hey, I just saw this on the Github WASM thread, looks cool! I'm interested, but if I may request, you should highlight the missing/non-fully-functional keywords. That's my main concern, and from the main page it sounded like this was a fully working Go. Yet the Github issues seemed to highlight several missing keywords.

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

    • matthewmueller 2338 days ago
      Thanks for the kind words. Yah I think you're right that I should make the current state more clear, not just where it's headed. FWIW, there's some more information on that lower down the page: https://mat.tm/joy/#next-steps
  • matthewmueller 2338 days ago
    Hey folks! I've been hard at work building this compiler for the last few months and I'm very excited to finally be able to share it with you.

    I'll be here to answer any questions you might have!

    • andrewl-hn 2338 days ago
      Hey, great work! Just a heads up about licensing. JavaScript code fragments that you use inside the compiler to produce the final output are technically part of the source code, and thus the output is also GPLv3 licensed as a derived work.

      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.

      • matthewmueller 2338 days ago
        Thanks for the heads up! I was hoping for someone with more licensing knowledge to stop by :-)
    • zellyn 2338 days ago
      I command-F searched for GopherJS, looking for the obvious question -- how is this different? -- but found nothing besides crediting it as “inspiration”.

      So, how is this different?

      EDIT: asked in the Golang slack. Will update when I find out the answer.

      • vanderZwan 2338 days ago
        Not OP, but GopherJS is an emulator:

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

        [1] https://gist.github.com/rolaveric/9407509

        • nteon 2338 days ago
          GopherJS is _not_ an emulator. Saying that it emulates a 32-bit environment means that `int` (which is architecture-specific in Go) is 4 bytes (compared to 8-bytes on amd64), and means that int64 is supported and does what you expect.

          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.

          • vanderZwan 2338 days ago
            I stand corrected, apologies for spreading incorrect information. Sadly I can't edit my post any more.
      • matthewmueller 2338 days ago
        Hey sorry for the oversight there, I'll be documenting this in further in the next few days, but for now you can head over to: https://github.com/matthewmueller/joy/issues/56 to read more
    • trog 2338 days ago
      "The Go code is on the right and the compiled Javascript code is on the left. "

      I am not very familiar with Go and am only barely passable at Javascript - but aren't these the wrong way round?

    • lobster_johnson 2338 days ago
      Hi, this looks great! Quick question:

      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?

    • matthewmueller 2338 days ago
      Heading to bed now.

      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!

    • schickling 2338 days ago
      I'm very much looking forward to the Next.js-like framework you've teasered!
    • wyuenho 2338 days ago
      Hey nice work! Can you tell us a little about why you've created this and its utility for the general public? Thanks!
    • sAbakumoff 2338 days ago
      I have the only question and I would really appreciate to get a clear answer instead of many down votes. Why are you doing this?
      • whichdan 2338 days ago
        There's an entire section on this on the author's website.
      • fiatjaf 2338 days ago
        Doing what?
  • m00s3 2338 days ago
    • HumanDrivenDev 2338 days ago
      Very appropriate, since googles go did the exact same thing.

      https://en.wikipedia.org/wiki/Go!_(programming_language)

    • matthewmueller 2338 days ago
      Hmm, good catch. Let's see how it plays out :-)
      • carapace 2338 days ago
        I came here to say the same thing in re: the name conflict with Joy PL. I'm currently working on a Joy interpreter. I'm just getting it ready to post to PyPI (it's implemented in Python.)

        It's pretty obscure, but I have high hopes for the language. It has some amazing qualities.

        • matthewmueller 2338 days ago
          Awesome!

          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.

          • carapace 2337 days ago
            Weird, I thought I deleted that comment.

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

      • nerdponx 2338 days ago
        Why not call it JoyGo or JoyJS or Go2js or something? No reason to cause name (and command line) confusion just because you like a name.
        • Sir_Cmpwn 2338 days ago
          Joy is coming up on 15 years without a release, there should probably be a statute of limitations on this sort of thing.
          • shabbyrobe 2338 days ago
            Alas, Manfred von Thun is no longer with us. Seems unlikely there will be another release.
            • petecox 2338 days ago
              Manfred taught me mathematical logic back in the mid 90s. It was only much later browsing functional programming topics that I discovered his language and that he had passed away.

              RIP.

              • carapace 2338 days ago
                What was he like?
                • shabbyrobe 2338 days ago
                  My mate has an awesome story about providing technical support to him on campus. I hope neither he nor the deceased mind me relating it.

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

                  • petecox 2337 days ago
                    Every staff member had one of those. They opened new computer labs at La Trobe in about 1995 but before that it was VTxxx terminals accessing a mixture of VMS or *nix, I believe.

                    I remember using vi in typesetting a paper with LaTeX before print previewing a DVI on one of the PC or Mac machines.

                    • shabbyrobe 2337 days ago
                      Awesome, do you have any more info about them you'd be willing to share? By the time my mate was around they weren't common enough in the humanities dept for him to have ever seen one before Manfred's. He's likely at least as curious as I am!
                      • petecox 2337 days ago
                        I was at La Trobe 1992-6 and Manfred taught me in 95 or 96.

                        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.

                • petecox 2337 days ago
                  He was a European gentleman in a remote land with a quirky sense of humour and generous spirit; not your typical stuffy academic in tweed. :) And he had an awesome beard, long before hipsters made them fashionable!

                  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/

                • carapace 2337 days ago
                  Thank you both so much! I really appreciate your taking the time to share.
          • JustSomeNobody 2338 days ago
            I disagree. You'll end up with new languages using the names of older languages. Besides, software can at some point be done.
            • Sir_Cmpwn 2338 days ago
              Software can also fade into irrelevance, which is what has happened to Joy.
              • a-nikolaev 2338 days ago
                Joy is a mathematical language similar to lambda calculus. It's getting old very slowly, slower that this compiler.
                • carapace 2338 days ago
                  Yes, Joy is amazing. I have been working through the Advent of Code puzzles with it and the code keeps coming out error-free. It delivers on Backus' idea of algebra of programs (aka "Functional Programming") in a direct and entertaining way. It also seems amenable to efficient compilation.

                  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

        • weberc2 2338 days ago
          Guaranteed unique project name generator: `uuidgen`
  • tboyd47 2338 days ago
    This is AWESOME.

    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.

    • matthewmueller 2338 days ago
      Thanks for the kind words of encouragement!
  • readams 2338 days ago
    Looks interesting but I think WebAssembly remains the more promising path for compiling to web browsers at this point. x to JS transpilers are likely on the way out.
    • IshKebab 2338 days ago
      True, but right now this is the better approach because you can access the DOM, and presumably make use of Javascript's garbage collector.
  • dinedal 2338 days ago
    How is this different from the more established GopherJS?
    • Touche 2338 days ago
      From an issue in the GitHub, it sounds like GopherJS has a slightly different goal; it is attempting to make it possible to compile existing Go libraries / projects, whereas Joy is more focused on new projects built specifically to run in the browser.
  • rkeene2 2334 days ago
    On startup (with no arguments, so just "help" output) it tries to read my ~/.aws/credentials file and there seems to be some kind of tracking going on: https://github.com/matthewmueller/joy/blob/master/internal/s...

    I almost used this software, but I'm going to have to go through the code before I do now.

  • 52-6F-62 2338 days ago
    Hey Matt, I received this error when trying to compile a "hello world" for the first time:

        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.

  • kindfellow92 2338 days ago
    There is a statement in that document that says that much of the standard library hasn’t been translated but isn’t most of the Go standard library written in Go? Why can’t Joy convert the standard library?
    • matthewmueller 2338 days ago
      time. never enough time ;-)
      • kindfellow92 2337 days ago
        Well, the go standard library is mostly written in Go, and Joy is supposed to convert go... so shouldn’t this just work?
  • ridiculous_fish 2338 days ago
    How are Go's pointers implemented in JS?
    • matthewmueller 2337 days ago
      This is not done yet. Right now there's no difference between pointer values and non-pointer values.
  • kotrunga 2338 days ago
    Do you have a personal website / blog?

    I could be completely missing something, but mat.tm is down.

    • matthewmueller 2338 days ago
      Weird, maybe a DNS issue? Can you try again?
  • srameshc 2338 days ago
    What a coincidence. I was thinking when would something like this be out yesterday and it stayed just a thought. Didn't bother to google and now I see it here. Something I would certainly love to try.
  • schickling 2338 days ago
    This looks amazing! Is there some demo video available?
    • matthewmueller 2338 days ago
      Thanks! Not yet, but I'm planning to make some videos very soon :-)
  • dfabulich 2338 days ago
    It advertises VDOM support, but Go/Joy doesn't appear to have anything like JSX, right? (JoySX?)
    • matthewmueller 2338 days ago
      No JSX – VDOM would mean things what JSX turns into e.g. `React.createElement(...)`
    • fiatjaf 2338 days ago
      I hope not.
  • sAbakumoff 2338 days ago
    > Translate idiomatic Go into concise Javascript that works in every browser. Use Go's type system and world-class tooling to build large web applications with confidence.

    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

    • matthewmueller 2338 days ago
      I was a heavy Typescript user and a big fan. I personally found Go's type system and overall ecosystem to be much easier to grok, especially when it came to interacting with 3rd party packages. If you read through https://mat.tm/joy/#why you'll read more about my perspective there.

      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.

      • matthewmueller 2338 days ago
        Let me attempt to clarify a few things with fresh eyes:

        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.

        • boomlinde 2337 days ago
          > Javascript doesn't have threads, so true coroutines not really possible (w/o webworkers).

          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.

        • sAbakumoff 2337 days ago
          The only problem is co-rotines are not really useful in the fat client SPA's. They are all about data flow and event handling.
      • MatthewPhillips 2338 days ago
        Hi Matt! First congratulations. This is a very interesting project, one that I look forward to trying out.

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

      • sAbakumoff 2338 days ago
        Wait, async/await and co-rotines are completely different concepts, aren't they? the former just separate the moment of execution from the moment of receiving the result, the latter allow to execute the code in parallel. In browser the parallelism is only possible with web-worker.
      • sAbakumoff 2338 days ago
        Did you try Angular 4 + TypeScript? I recently switched to it after years in React and that's amazing, google really did it right this time. After using it for a while I don't feel any need in any additional tools.
    • slimsag 2338 days ago
      > we already have type script. Secondly, the post powerful Golang feature which is you know co-routines can't be translated to javascript

      FYI GopherJS (the original Go -> JavaScript transpiler) has full support for goroutines. So "can't be translated to javascript" isn't quite right.

      • zaarn 2337 days ago
        GopherJS implements goroutine "emulation" over JS, it cheats a bit there (it also emulates integers and does other hacks to make JS compatible)
    • geofft 2338 days ago
      > Thanks, but for type system we already have type script.

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

      • sAbakumoff 2338 days ago
        The author stated below that co-routines are translated to async/await. for me it seems to be completely different concepts because golang co-rotines allow to execute the code in parallel which async/await can't do.
        • jrs95 2338 days ago
          Given that the Go runtime will put any number of goroutines on any number of threads, it seems like being limited to one thread in a JS environment shouldn't break anything. The concurrency model works regardless of the number of underlying threads.
          • sAbakumoff 2338 days ago
            That's right, concurrency model does not break anything but still there are multiple concerns :

            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)

            • randomdata 2338 days ago
              > in fat client apps it's all about event handling and data flow, co-rotines are not very useful there.

              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.

            • jrs95 2338 days ago
              1) I don't think it actually uses async/await as it explicitly targets ES3. It's probably just using callbacks or something.

              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.

              • sAbakumoff 2337 days ago
                1) It does not really matter that you think because the author said the following:

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

          • geofft 2338 days ago
            I suspect "works" is strong - if there's no preemption, it's very easy to hit a deadlock. Consider a program that e.g. mines bitcoin on one goroutine and displays UI on the other. On any normal platform, the UI goroutine would get scheduled on a thread at least occasionally, but if you only have one thread to go around and no preemption, the mining task could just keep mining forever.
            • chrisseaton 2338 days ago
              This doesn't make any sense to me.

              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?

              • geofft 2338 days ago
                The first task is writing to the second when it's done with a computation, but not bothering to check input from the second while it's in the middle of a computation.

                (Maybe I'm wrong and Go handles this smoothly?)

                • chrisseaton 2338 days ago
                  Ah I see. I don't work in UIs so don't think about user responsiveness.
                • jrs95 2338 days ago
                  This will work fine as long as you're using a separate goroutine for each.
                  • geofft 2338 days ago
                    Well, this works as long as you're using a separate goroutine and the Go runtime creates more than one thread, right? My claim is that a Go runtime that only creates one thread (which is effectively what Joy is) will not work the way you expect in this case.

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

                    • jrs95 2337 days ago
                      That isn't any different from anything else in the browser though. It's not going to lock up anymore than async JS code would during CPU intensive operations. Which generally don't need to be done in browsers anyways.
        • geofft 2338 days ago
          I don't know too much about Go, but I think that background computations can be converted to web workers. Looks like Joy doesn't do it right now, but again, it doesn't seem fundamentally impossible.

          (Also, it wouldn't surprise me if the majority of goroutines in practice were I/O heavy and not computationally heavy.)

        • chrisseaton 2338 days ago
          > allow

          This is the key word. It is never guaranteed, so apps don't require it.