{"action":"created","issue":{"url":"https://api.github.com/repos/tc39/proposal-bind-operator/issues/44","repository_url":"https://api.github.com/repos/tc39/proposal-bind-operator","labels_url":"https://api.github.com/repos/tc39/proposal-bind-operator/issues/44/labels{/name}","comments_url":"https://api.github.com/repos/tc39/proposal-bind-operator/issues/44/comments","events_url":"https://api.github.com/repos/tc39/proposal-bind-operator/issues/44/events","html_url":"https://github.com/tc39/proposal-bind-operator/issues/44","id":203206592,"number":44,"title":"Drop the `this` binding altogether","user":{"login":"isiahmeadows","id":4483844,"avatar_url":"https://avatars1.githubusercontent.com/u/4483844?v=4","gravatar_id":"","url":"https://api.github.com/users/isiahmeadows","html_url":"https://github.com/isiahmeadows","followers_url":"https://api.github.com/users/isiahmeadows/followers","following_url":"https://api.github.com/users/isiahmeadows/following{/other_user}","gists_url":"https://api.github.com/users/isiahmeadows/gists{/gist_id}","starred_url":"https://api.github.com/users/isiahmeadows/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/isiahmeadows/subscriptions","organizations_url":"https://api.github.com/users/isiahmeadows/orgs","repos_url":"https://api.github.com/users/isiahmeadows/repos","events_url":"https://api.github.com/users/isiahmeadows/events{/privacy}","received_events_url":"https://api.github.com/users/isiahmeadows/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":81,"created_at":"2017-01-25T19:59:45Z","updated_at":"2018-03-19T18:24:16Z","closed_at":null,"author_association":"CONTRIBUTOR","body":"**Edit:** Here's specifically what I'm proposing:\r\n\r\n- Keep the function pipelining: `object::func(foo, bar, baz)`, equivalent to `func.call(object, foo, bar, baz)`\r\n- Drop the binary binding operator: `object::func`, equivalent to `func.bind(object)`\r\n- Drop the unary binding operator: `::object.func`, equivalent to `object.func.bind(object)`\r\n\r\nNote that this is independent of the syntax or semantics of the function pipelining itself (see #26 for an in-depth discussion on that and the old binding operator, and #40 for a more recent proposal specific to that), and is exclusively focused on dropping the binding syntax.\r\n\r\n-----\r\n\r\nThe resource usage for general `this` binding leads to a lot of confusion:\r\n\r\n```js\r\n// This works\r\nvar listener = ::console.log\r\n\r\nelem.addEventListener(\"click\", listener, false)\r\nelem.removeEventListener(\"click\", listener, false)\r\n\r\n// But this doesn't\r\nelem.addEventListener(\"click\", ::console.log, false)\r\nelem.removeEventListener(\"click\", ::console.log, false)\r\n```\r\n\r\nThose of us familiar with the proposal would immediately know this, but those less familiar would expect the opposite (which would be much more wasteful of memory, because JS doesn't have the lifetime management awareness of Rust and C++).\r\n\r\nAlso, for the binary version, `object::method` without an immediate call doesn't really help much at all for expressiveness.\r\n\r\nHere's what I propose: drop the `this` binding altogether, and keep it limited to just immediate calls. I'm not proposing anything about where the object is passed (using `this`/first argument/etc.), or even the operator used, just not including binding in the proposal.\r\n\r\nFirst, here's the equivalents for each one, using `Function.prototype.bind` and arrow functions, just for comparison:\r\n\r\n```js\r\n// Property binding\r\n::console.log\r\nconsole.log.bind(console)\r\nvalue => console.log(value)\r\n\r\n// Function binding\r\nobject::method\r\nmethod.bind(object)\r\nvalue => method.call(object, value)\r\n```\r\n\r\n`Function.prototype.bind` is already easily optimized for a single argument. In addition, property and method binding is rarely chained (I've never seen it done, ever). How often do you see anything like this? Chances are, probably never, or if you have, it was likely an obvious refactor.\r\n\r\n```js\r\nmethod.bind(console.log.bind(console))\r\n(::console.log)::method // Using the current proposal\r\n```\r\n\r\nAdditionally, if you need to bind after chaining, it's fairly easy to just create a new variable, and naming isn't usually hard for simple cases like these.\r\n\r\n---\r\n\r\nBut the method chaining still has its benefits:\r\n\r\n1. Method chaining will avoid ugly nested calls like this:\r\n\r\n    ```js\r\n    // Now\r\n    var list = _.uniq(_.flatten(_.map(items, v => v.getName())))\r\n    // Better\r\n    var list = items\r\n        ::_.map(v => v.getName())\r\n        ::_.flatten()\r\n        ::_.uniq()\r\n    ```\r\n\r\n    That would make things way easier to read, because the steps are more sequential, and fewer parentheses are involved. Functional languages frequently have something like this for similar reasons, like Elm/LiveScript/OCaml/F#'s `x |> f` operator. They helpfully avoid parentheses due to their low associativity and left-to-right application, making logic much easier to read.\r\n\r\n2. Wrapper libraries can leverage ES modules and Rollup's tree-shaking feature to not ship more than necessary, yet still retain the convenient pseudo-method syntax. You could create a Lodash clone that only calls the methods you need, so if you only use `map`, `filter`, `reduce`, and `forEach`, you only bundle those at runtime, even when you install the whole library from npm. Basically, what you don't use, you don't pay for.\r\n\r\n---\r\n\r\nSo I still want the binary version to allow calls, but let's get rid of the `this` binding. It's confusing and unintuitive for newcomers, and hardly provides any benefit in practice."},"comment":{"url":"https://api.github.com/repos/tc39/proposal-bind-operator/issues/comments/374316143","html_url":"https://github.com/tc39/proposal-bind-operator/issues/44#issuecomment-374316143","issue_url":"https://api.github.com/repos/tc39/proposal-bind-operator/issues/44","id":374316143,"user":{"login":"m93a","id":1671665,"avatar_url":"https://avatars0.githubusercontent.com/u/1671665?v=4","gravatar_id":"","url":"https://api.github.com/users/m93a","html_url":"https://github.com/m93a","followers_url":"https://api.github.com/users/m93a/followers","following_url":"https://api.github.com/users/m93a/following{/other_user}","gists_url":"https://api.github.com/users/m93a/gists{/gist_id}","starred_url":"https://api.github.com/users/m93a/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/m93a/subscriptions","organizations_url":"https://api.github.com/users/m93a/orgs","repos_url":"https://api.github.com/users/m93a/repos","events_url":"https://api.github.com/users/m93a/events{/privacy}","received_events_url":"https://api.github.com/users/m93a/received_events","type":"User","site_admin":false},"created_at":"2018-03-19T18:24:16Z","updated_at":"2018-03-19T18:24:16Z","author_association":"NONE","body":"On tc39/proposal-pipeline-operator#110 I've done a summary of the similarities and differences between the Bind Operator and the Pipeline Proposal and I found out that the part promoted by @isiahmeadows is really the only part we need. The rest can be quite easily done with the [Smart Pipelines](https://github.com/js-choi/proposal-smart-pipelines/). Be sure to check the issue out, as this is IMHO the most probable way of getting the “function pipelining”, as Isiah calls it, to the specs!"}}
{"actor":{"display_login":"m93a"}}