Greenspuns tenth rule: “Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.”
I’ve always wanted a clojure style thread operator [1] in other languages :)
It is interesting to note the overhead it has to define such simple construct in JavaScript. Pages and pages of a spec, all the work to herd ppl behind the proposal, etc.
In Clojure, the threading macros are awesome and they are not even a language construct, just some ~10 lines of code per macro! [1]
I used to think the same, until it was pointed out to me that the semantics have to be nailed down exactly, so that conforming implementations (e.g. Chrome/FF) do the same thing. This includes figuring out how (if at all) it works with generators and async functions, if you want to support implicit lambdas, etc[1]. Clojure and ML (and related languages I imagine) have the advantages that it is expressible in code which at least makes the specification part simpler.
Fortunately the simple version is easily approximated, I have this sprinkled in various files where it's useful:
What happened to the bind operator (::)? I do miss threading macros from Clojure but I don't see them as solving a real problem in the javascript language. A shortcut for binding `this`, on the other hand, would have saved me a lot of time wondering why my React component methods weren't working correctly.
It went through a bunch of iterations that simplified it, it used to be the abstract references operator which I believe would have a symbol lookup on the target function that would then allow the function to take over execution, thus allowing you to decide if the function would explicitly take the called upon object as `this` or as the first argument.
It gradually got simplified but nobody could agree about the behaviour of if this would _just work_ with existing functions via the `this` or the first argument, I think eventually the proponents if it grew tired of the battle, they couldn't get unified support for one way or the other.. interesting the pipeline operator has basically gone through the exact same issues, but seems to have had much more attention to it.
Ultimately I believe the bind operator was just too soon, generally at the time people were still trying to come to terms with what was a lot of new syntax coming to javascript, as well as react and similar things, now I think these chaining operators make a lot more sense to a lot more people.
Wouldn't that be problematic if you're binding lots of handlers, though? It seems like the fat arrow syntax here is creating a new anonymous function for every instance of the handler.
And if you've got a list of tens or hundreds of items, and you want a click handler for each, you quickly get to the point where all the extra overhead matters.
Like, for instance, in a React render function you could have
But option #1 would be a lot less efficient if you've got lots of things, since it's creating a new closure that calls the instance method instead of just pointing at the instance method like snipper #2 does.
I still see lots of people recommending #1 for this exact scenario, though. Maybe I'm just wrong, or maybe stuff like this is why I see so many SPAs consuming shocking amounts of memory.
I grant that using the fat arrow is probably fine for the scenario you mentioned though, with something like a text field. I don't think I've seen many pages with so many text fields that the extra overhead would even make a difference.
The latter version seems to be the one I most commonly see, except _handleClick() is just handleClick() repeated. Am I correct in assuming this is considered idiomatic at this point?
Is this better somehow? I feel like I should know this, but it's Friday night and I'm tired, but isn't the constructor fired on every instance of the component? And if so, is this a better approach for any particular reason other than clarity?
It is fired on every instance of the component. However, if you create the arrow function in the render function, it'll be created for every render. Since React keeps the component instances around between renders, it can be a lot better.
I don't have any benchmarks so I won't speculate which is faster, but both these options create a new function object. The fact that one is done implicitly doesn't necessarily make it faster. I suspect performance will be highly engine- and version-specific, so best to choose the more idiomatic one (which I leave as an exercise for the reader to figure out).
The moment es6 classes showed up without automatic method binding was the moment I fell out of love with JavaScript.
I can't imagine that there would EVER be a good reason not to have a method bound to the class. Now we've all been forced to learn this new property initializer syntax and add yet another babel dependency to facilitate it.
Don't they still have to wait for the spec to finalize / hit stage 3?
Don't get me wrong, I'm super excited for this functionality because I love it in languages like F# and Elixir, but it looks like the pipe proposal is still stage 1.
While I think this is a risky move, I had the impression that the ratification of new features was mainly based on the implementations.
So, first the runtimes/compilers implement it and then it gets into the spec.
TypeScript sees itself as a superset of ECMAScript, so its ECMAScript parts are just another implementation of the spec, like Node, Babel and the browser engines.
> Don't they still have to wait for the spec to finalize / hit stage 3?
Yes, this appears to be just a tracking issue, not an impending implementation (and definitely not a PR). The "Waiting for TC39" label added even has the tooltip "Unactionable until TC39 reaches some conclusion".
It seems unfortunate that JavaScript is evolving so quickly these days. There is more syntax than anyone who isn't a full-time web developer will be able to remember.
There's been a lot of new features added in ES6+ but not a huge amount of new syntax overall (a lot of the new features are things like array and object methods, etc.)
All of the new syntax is technically optional, but at least some percentage of it just makes it easier for newer/less-experienced devs to write things: e.g. classes as simplified syntactic sugar around prototype-based inheritance models, or function parameter spread operators to make learning how to arguments.whatever unnecessary and generally make code for dynamic argument lengths easier to understand.
No matter when you started learning Javascript there would have been parts too complex or obscure to learn immediately (the prototype-based inheritance model is something I think a lot of full-time professional JS devs don't fully grok). There was always things you learn first and things you learn later. With the new syntax, I think now the things* you learn first are just more likely to be immediately useful.
* where "things" excludes learning how to master every trending new library—that is a part of Javascript that isn't improving unfortunately.
I find this to be a bit of a cop out, there's still less syntax than something like C# or Java, and plenty of developers are ok with those.. JavaScript went through years of nothing and then sudden change.. if you were only casually interested in it (say, a backend developer who just puts some js together) then criticizing seems unfair.. you can continue to write the exact same code, but expect those who write it as their primary language care a hell of a lot more about it being succinct and powerful.
Greenspuns tenth rule: “Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.”
I’ve always wanted a clojure style thread operator [1] in other languages :)
[1] https://clojure.org/guides/threading_macros
It is interesting to note the overhead it has to define such simple construct in JavaScript. Pages and pages of a spec, all the work to herd ppl behind the proposal, etc.
In Clojure, the threading macros are awesome and they are not even a language construct, just some ~10 lines of code per macro! [1]
In ML, the pipe operator is even shorter:
1: https://github.com/clojure/clojure/blob/4ef4b1ed7a2e8bb0aaaa...I used to think the same, until it was pointed out to me that the semantics have to be nailed down exactly, so that conforming implementations (e.g. Chrome/FF) do the same thing. This includes figuring out how (if at all) it works with generators and async functions, if you want to support implicit lambdas, etc[1]. Clojure and ML (and related languages I imagine) have the advantages that it is expressible in code which at least makes the specification part simpler.
Fortunately the simple version is easily approximated, I have this sprinkled in various files where it's useful:
[1] https://babeljs.io/blog/2018/07/19/whats-happening-with-the-...The converse is also true when you want to do side-effecty stuff in Haskell.
What happened to the bind operator (::)? I do miss threading macros from Clojure but I don't see them as solving a real problem in the javascript language. A shortcut for binding `this`, on the other hand, would have saved me a lot of time wondering why my React component methods weren't working correctly.
It went through a bunch of iterations that simplified it, it used to be the abstract references operator which I believe would have a symbol lookup on the target function that would then allow the function to take over execution, thus allowing you to decide if the function would explicitly take the called upon object as `this` or as the first argument.
It gradually got simplified but nobody could agree about the behaviour of if this would _just work_ with existing functions via the `this` or the first argument, I think eventually the proponents if it grew tired of the battle, they couldn't get unified support for one way or the other.. interesting the pipeline operator has basically gone through the exact same issues, but seems to have had much more attention to it.
Ultimately I believe the bind operator was just too soon, generally at the time people were still trying to come to terms with what was a lot of new syntax coming to javascript, as well as react and similar things, now I think these chaining operators make a lot more sense to a lot more people.
You can use the fat arrow syntax to implicitly bind a function to this:
Wouldn't that be problematic if you're binding lots of handlers, though? It seems like the fat arrow syntax here is creating a new anonymous function for every instance of the handler.
And if you've got a list of tens or hundreds of items, and you want a click handler for each, you quickly get to the point where all the extra overhead matters.
Like, for instance, in a React render function you could have
or But option #1 would be a lot less efficient if you've got lots of things, since it's creating a new closure that calls the instance method instead of just pointing at the instance method like snipper #2 does.I still see lots of people recommending #1 for this exact scenario, though. Maybe I'm just wrong, or maybe stuff like this is why I see so many SPAs consuming shocking amounts of memory.
I grant that using the fat arrow is probably fine for the scenario you mentioned though, with something like a text field. I don't think I've seen many pages with so many text fields that the extra overhead would even make a difference.
Having .bind inside a JSX prop also creates a new anonymous function on each render.
To avoid it, you can do (sorry for bad formatting):
You can also bind handleClick inside the constructor without the arrow.The latter version seems to be the one I most commonly see, except _handleClick() is just handleClick() repeated. Am I correct in assuming this is considered idiomatic at this point?
Yes, I'd say so.
Is this better somehow? I feel like I should know this, but it's Friday night and I'm tired, but isn't the constructor fired on every instance of the component? And if so, is this a better approach for any particular reason other than clarity?
It is fired on every instance of the component. However, if you create the arrow function in the render function, it'll be created for every render. Since React keeps the component instances around between renders, it can be a lot better.
Ah, that makes sense. Do you by any chance know of any articles that go further into how this works?
https://pbs.twimg.com/media/DZ-97vzW4AAbcZj.jpg:large
Perfect!
I don't have any benchmarks so I won't speculate which is faster, but both these options create a new function object. The fact that one is done implicitly doesn't necessarily make it faster. I suspect performance will be highly engine- and version-specific, so best to choose the more idiomatic one (which I leave as an exercise for the reader to figure out).
The moment es6 classes showed up without automatic method binding was the moment I fell out of love with JavaScript.
I can't imagine that there would EVER be a good reason not to have a method bound to the class. Now we've all been forced to learn this new property initializer syntax and add yet another babel dependency to facilitate it.
There was a proposal for decorators that clearly handled this that seems to have been deprecated (it’s not included in Babel anymore).
The whole binding in the constructor seems like needless noise to meNote that the proposal for a pipeline operator is still in its early day. In fact, there are two proposals (https://babeljs.io/blog/2018/07/19/whats-happening-with-the-...) and so far there's no clear winner. Seems like there's still a long way to go.
Anyway, which style do you prefer?
Neither. Just use a function. You don't need a dedicated operator in the language's syntax to composite functions.
Now try writing the type declaration for your pipeline function...
a -> (a -> b) -> (b -> c) -> c
Don't they still have to wait for the spec to finalize / hit stage 3?
Don't get me wrong, I'm super excited for this functionality because I love it in languages like F# and Elixir, but it looks like the pipe proposal is still stage 1.
https://github.com/tc39/proposals/blob/master/README.md
While I think this is a risky move, I had the impression that the ratification of new features was mainly based on the implementations.
So, first the runtimes/compilers implement it and then it gets into the spec.
TypeScript sees itself as a superset of ECMAScript, so its ECMAScript parts are just another implementation of the spec, like Node, Babel and the browser engines.
> Don't they still have to wait for the spec to finalize / hit stage 3?
Yes, this appears to be just a tracking issue, not an impending implementation (and definitely not a PR). The "Waiting for TC39" label added even has the tooltip "Unactionable until TC39 reaches some conclusion".
Livescript (which was supposed to replace CoffeeScript) also has it.
It seems unfortunate that JavaScript is evolving so quickly these days. There is more syntax than anyone who isn't a full-time web developer will be able to remember.
There's been a lot of new features added in ES6+ but not a huge amount of new syntax overall (a lot of the new features are things like array and object methods, etc.)
All of the new syntax is technically optional, but at least some percentage of it just makes it easier for newer/less-experienced devs to write things: e.g. classes as simplified syntactic sugar around prototype-based inheritance models, or function parameter spread operators to make learning how to arguments.whatever unnecessary and generally make code for dynamic argument lengths easier to understand.
No matter when you started learning Javascript there would have been parts too complex or obscure to learn immediately (the prototype-based inheritance model is something I think a lot of full-time professional JS devs don't fully grok). There was always things you learn first and things you learn later. With the new syntax, I think now the things* you learn first are just more likely to be immediately useful.
* where "things" excludes learning how to master every trending new library—that is a part of Javascript that isn't improving unfortunately.
I find this to be a bit of a cop out, there's still less syntax than something like C# or Java, and plenty of developers are ok with those.. JavaScript went through years of nothing and then sudden change.. if you were only casually interested in it (say, a backend developer who just puts some js together) then criticizing seems unfair.. you can continue to write the exact same code, but expect those who write it as their primary language care a hell of a lot more about it being succinct and powerful.
I was hoping we'd get something like PowerShell pipelines, which work on iterators, passing each item through as it's generated.
Those are incredibly powerful, and as a lot to the language, whereas this just seems like fairly simple syntactic sugar.