-
Notifications
You must be signed in to change notification settings - Fork 6
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
Why :: need to be used while defining? #8
Comments
First, only binary form need defining first, or The design goal is making extension (virtual) methods/properties behave as close as normal (real) methods/properties. The only difference between them is how to lookup the methods/properties.
When get the method, all invoke the method with the receiver Note One such problem of old proposal (lookup Another benefit of defining first is it could give error in more early stage. https://www.smashingmagazine.com/2018/10/taming-this-javascript-bind-operator/ have a good example: const plus = (x) => this + x;
...
1::plus(1) // expect 2 but got "[object Window]1" or NaN or possible some other values With this new proposal, we could throw type error in first place. Of coz, it seems forcing defining is not as convenience as old proposal, but consider the common usage is importing extension methods from modules, with |
Note, I understand it's not common to have separate namespace in JS, I'm still investigating the other options which mitigate the problem. One possibility is remove
which seems more consistent and simpler. It still in separate namespace but may be more acceptable... |
Another point, if we really want applying method from a local binding directly, we could have syntax like
|
I’m not sure i see the case for a separate namespace at all. I don’t recall the old proposal being considered to have any problems related to |
@ljharb I hope I could express the ideas clearer: High-level goal: make extension methods behave as close as real methods in syntax, semantic and developer experiences; eliminate the barrier and troubles of using extensions as possible as we can. Old proposal issues which affect this goal:
|
I'm not clear on how that's a refactoring hazard. "Adopting a linter" is not really a cost; everyone who's going to use one likely already has one - but shadowing is also a normal part of the language, and it's often desired to shadow. Why does a function need conversion? |
The refactoring hazard is programmers are forced to either rename the local variable or rename the extension method name. And naming is hard. "Adopting a linter" (and adopting special rules) is always a cost. But I don't want to argue this point with you again and again.
I somewhat agree. This is why people often override and disable no-shadow rule when they use some coding style (like airbnb eslint config) which enable no-shadow by default. The point here is, when someone use
Because most libraries provide util functions like |
I don't understand why that's something we'd want to support. Methods used as if they're in a chain should be ones written to be used as such - just like decorators aren't designed to be used with functions that weren't written to be decorators. A user who wants that can |
Actually I agree that. The point here is , actually there is no much differences between these two The reason why lodash (and other util libs) is written like that is just because the language do NOT have extension methods. Library authors are forced to provide the functions in util function form. So if we introduce extensions in language level, it would be better to levage the assets if possible, not force every libraries write the same conversion logic, and publish a new versions , and users have to upgrade to new versions to use the feature. |
I don't think that would be better. I think that libraries like lodash would either provide forms that use |
This question would be better answered by library maintainers. But I at least see some factors :
Note every library need to repeat that. And also there are tons of libraries have no active maintaining. |
As a library maintainer, I would prefer that functions I write to not use You don't need two packages, but you could easily have one package with two entry points. |
I've used Lodash via "lodash-bound" before and I thought it should be considered when evaluating how 3rd party libraries can adapt to this operator. I used it against the same babel implementation of the :: operator that we've always had. I'm not at a desktop or I might go into greater detail. :) |
Could you explain what bug reports will occur? I hope we can try to analyze and avoid them. |
Any time someone uses a package in a way the author didn’t intend, there’s a likelihood of new bugs. An automatic adapter is very unlikely to be able to handle all edge cases, including “the second argument is the receiver”, or “it’s sloppy mode but i don’t expect the global object” or “it’s strict mode but i do expect the global object” or “it’s sloppy mode but i do expect a primitive receiver” or the inverse, etc. |
@ljharb Thank you for provide such cases, I'd like to do some research on these cases. If you could provide some real world cases of them it will be much helpful. Thank you very much! |
I don't have anything concrete to share. You're welcome to look over my packages for examples; the main thing is, that if i don't explicitly intend a function to be used with a receiver, it should simply not be differently usable in a receiver position. For example, with any function |
With the pipeline proposal reaching Stage 2 I'm not convinced that conversion utilities are as a critical part of an extensions proposal going forward. Even with extension methods we could just mix them with pipelining as needed, rather than trying to convert everything into one: import { flatMap } from "./iterableUtils.js";
import { sortBy } from "lodash";
import { takeMiddle } from "./arrayUtil.js";
myCollection
::flatMap((i) => [i, i])
|> Array.from(^)
|> sortBy(^, item => item.id)
::takeMiddle(5); I do think the const plus = (x) => this + x;
...
1::plus(1) hazard is a bit unfortunate though, although for one this can be solved by tools like TypeScript, or even just unit testing. Although if using arrows in such a way were still sufficiently desirable, we could just make // possible syntax
const plus = (this, x) => this + x;
1::plus(1); // 2 The concern about shadowing, (i.e. Also having previously used the older bind operator proposal with Babel quite a bit a few years ago, I can say from experience it was easy enough to work with that I don't think huge changes were super neccessary. For functions written specifically to be this-taking methods, it was always trivial to work with. There was some boilerplate with converting some operations, but for the most part it wasn't too bad, and if pipelines had been a thing back then I don't think it would've been a problem at all. |
For me this is a non-starter. I don't understand the need for namespacing after reading this whole issue, and I prefer the old proposal. I feel like this proposal has way more complexity. For me, the main value for this operator is a new calling style for functions that are already in scope and with this proposal, that wouldn't be allowed. |
I saw the proposal is
const ::toArray=...
now.Why not
const toArray=...
simply, like old proposal did?The text was updated successfully, but these errors were encountered: