Skip to content

Discussion/Proposal: Addressing the idiomatic mismatch between JavaScript and Go #401

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
flimzy opened this issue Feb 14, 2016 · 7 comments

Comments

@flimzy
Copy link
Member

flimzy commented Feb 14, 2016

This is an issue that's been rolling around in my head for several months. It's more a discussion topic than a specific bug/issue.

As background, I don't know precisely what objectives @neelance had in mind when writing GopherJS. I gather the primary goal (aside from proving it could be done) was to run Go code in the browser. It seems this goal has been largely acheived, with good support for most of the Go standard library. But my primary reason for using GopherJS is to replace JavaScript as the language for writing client-side code. I think it's the other side of the same coin. Toward that end, I think there's room for some improvement.

Here I'd like to address two specific issues, closely related to each other.

The more general issue is that there's no defined style guidelines for GopherJS. There's no "GopherJS way." There is the "Go way" and there is the "JavaScript way" (or ways). And these are good in their own rights, but they are often incompatible, which leads to messy GopherJS Binding libraries. Most of the existing GopherJS bindings I've seen, lend themselves to writing JavaScript code in Go, complete with callbacks, event handlers, and everything else. This doesn't make for very idiomatic Go code, and it raises the barrier to entry, as one must understand both Go and JavaScript idioms to effectively use these libraries. And in many cases, these JavaScript-as-Go idioms can be avoided, by writing (IMO) better bindings.

In my experience, the most common casees where idioms of the two worlds crash are:

  • In the passing of optional arguments
  • In the use of callbacks for asynchronisity
  • Event-based programming

Other examples include data type conversions, error handling, null vs nil vs undefined, etc.

The second issue I wish to address is on a higher level. There are a large number of JavaScript APIs that don't have direct correlations in Go, but to be a full-fledged replacement for JavaScript in the browser, these need to be accessible. At the most primitive level, of course, they are accessible. By using .Get(), .Call(), and related functions in the gopherjs/js packages, literally anything can be accomplished. But that leads to very verbose, and hard-to-follow code, that isn't at all idiomatic Go.

We already have example bindings for some of these APIs. But there are many more which don't yet have bindings (to my knowledge). And at least some of the existing bindings don't make for especially idiomatic Go. The jQuery bindings expose the Deferred interface, which isn't idiomatic Go, and I believe could be more idiomatically exposed as synchronous operations (wrap it in a go routine if you need async). The websocket bindings provide both JS and Go idiomatic versions, which I think is an example of a good way to do things.

I expect some big improvements could be made toward idiomatic Go bindings of JS libraries.

This brings me to some possible responses to these issues:

Perhaps at minimum a GopherJS Bindings style guideline could be written. This might exist on the wiki page and/or in the gopherjs-book (is that still alive?). IMHO, this ought to cover suggestions of how to handle JS functions that accept multiple arguments, when (if ever) to expose Callback APIs, versus creating a synchronous wrapper around the underlying object (or perhaps providing both functionalities in the Go API), how events can or should be handled, how to handle errors returned by JS functions, etc.

With such guidelines in place, I think writing idiomatic Go bindings will become much easier. Which lends to...

Should GopherJS own the bindings for official JavaScript APIs? It already owns webgl and websocket bindings. Is there an interest in owning bindings for the File APIs, Worker APIs, Events, etc? If so, how should these various bindings be broken up by package? How can quality/adherence to the guidelines be ensured? Etc? (I don't expect answers to all of these questions now)

And finally, for non-official APIs (PouchDB, jQuery, etc), perhaps it would be worth mentioning in the bindings page which of them adhere to the style guidelines.

I know this leaves a lot of questions unanswered, such as "who's going to do this work?", not to mention "what will the guidelines actually contain?" I'm willing to contribute where possible. But I want this post to be primarily the beginning of this conversation, it doesn't have to answer all of the questions at once.

I'll wait to get some preliminary feedback, but I'm willing to start writing the rough draft of some bindings guidelines, and add them to the wiki (or whereever).

@myitcv
Copy link
Member

myitcv commented Feb 16, 2016

@flimzy I'm in following mode at the moment, but interested in following this work

@bep
Copy link

bep commented May 4, 2016

Agree. I believe this will eventually arrive naturally ... it is hard to know what's idomatic GopherJS until it is in your fingers. I have fiddled with some Facebook React "bindings" the last week. And I think part of the problem is that we call it "bindings" -- which to many translates to a 1:1 mapping.

@theclapp
Copy link

theclapp commented May 5, 2016

I think you've raise some important issues. I see three distinct proposals:

  1. Write a style guide. -- Good idea. Possibly premature, though. What's good style? Do we have a good example to point to? Maybe the websocket api, as you mentioned. It should cover documentation requirements, too. For example, in gopherjs/jquery, there isn't any. If you don't know jquery, you're on your own.
  2. Should GopherJS own the bindings for official JavaScript APIs. -- I think whoever writes them should own them until such time as they care to donate them to the gopherjs project, and the project has the resources to accept them (by which I mean, keep them up to date). This seems like a fairly minor issue to me. There are a lot of JS APIs; the GopherJS project trying to own, maintain, or coordinate them all could easily become problematic, and distract the maintainers from the core project. But if they (you) want to, more power to them.
  3. for non-official APIs (PouchDB, jQuery, etc), perhaps it would be worth mentioning in the bindings page which of them adhere to the style guidelines -- Sure.

This may be distinct from your proposal, but I'd also like to see some (more) basic documentation, perhaps in the Wiki, on basic usage. How you can use a Go struct (a struct without a *js.Object member), and how you can use a JS struct (a struct with a *js.Object member), and the pitfalls of trying to mix them or confuse them. (E.g. if you want to have a *js.Object member, it must be first, and all your other struct slots must have a js:"name" tag. And you can't initialize those slots directly in a struct literal.) These are all gotchas that significantly raised the bar for me and which I've found out by crawling through source, blog posts, and issues here. I'll probably just write some Wiki pages myself. They might be wrong, but it'll be easier for @neelance or @shurcooL to correct wrong stuff than write it all from scratch themselves.

And finally, GopherJS has a Google Group. Might I suggest that discussions such as this be held there?

Update: I just noticed that this was from 2/14. Sorry for being late to the party.

@bep
Copy link

bep commented May 5, 2016

Also, I think it would be fine to have bindings that live close to their JS counterpart, and then build more "Go like" libraries on top of those. It is hard to make a JQuery abstraction that doesn't look like jQuery -- but it is easier to build something better on top of a "jQuery like" Go API.

@dmitshur
Copy link
Member

dmitshur commented May 7, 2016

I think a great starting point for a style guide is for it to point to some existing bindings/libraries from https://github.com/gopherjs/gopherjs/wiki/bindings and suggest using them as a source to learn from.

I doubt maintaining a separate style guide is viable this early in this stage and with this few people actively working on it.

@nevkontakte
Copy link
Member

I have read through this issue, but I'm not quite sure what action is proposed here. Is it just that someone writes a document explaining how to make a Go-idiomatic bindings for a JavaScript API?

https://github.com/gopherjs/gopherjs/wiki/bindings already has a long-ish list of binding libraries, and I think by now we've established that binding libraries don't have to be owned by the GopherJS organization, perhaps except for the most commonly used ones.

@flimzy
Copy link
Member Author

flimzy commented Jun 26, 2023

I think this issue can be closed. It generated some good discussion, but as mentioned, there's no clear course of action proposed. Also, the situation has changed somwhat in the years since this was written, so any existing comments are mostly of historical value, not toward any actions we might take today.

Closing.

@flimzy flimzy closed this as completed Jun 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants