Skip to content
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

Introduction of new operator #58

Open
Haringat opened this issue May 4, 2022 · 13 comments
Open

Introduction of new operator #58

Haringat opened this issue May 4, 2022 · 13 comments

Comments

@Haringat
Copy link

Haringat commented May 4, 2022

To better differentiate between "bind and call" and "only bind, but do not call" I would introduce a new ::: operator beside the :: one.
The :: would only bind a function to the value before it:

const x = value::func(123);

would be equivalent to

const x = func.bind(value, 123);

The ::: operator on the other hand would call the bound function in-place:

const x = value:::func(123);

would be equivalent to

const x = func.call(value, 123);

The following would also work:

const x = value::(higherOrderFunc(123));

and would be equivalent to

const x = higherOrderFunc(123).bind(value);

And with ::::

const x = value:::(higherOrderFunc(123))();

which would be equivalent to

const x = higherOrderFunc(123).call(value);

So the two use-cases (which both occur frequently) would both be handled properly.

@ljharb
Copy link
Member

ljharb commented May 4, 2022

Why would we need to differentiate? Its a call if there’s invoking parens, it’s not if there’s not.

@Haringat
Copy link
Author

Haringat commented May 4, 2022

@ljharb Because that is not true in the examples stated above because the :: operator could also be used for property binding as described in the first example.

@ljharb
Copy link
Member

ljharb commented May 4, 2022

ah, i see what you mean.

This seems like it would be penalizing all the common cases in service of avoiding the need for parens in one exceedingly rare use case.

@Haringat
Copy link
Author

Haringat commented May 4, 2022

I am not sure but maybe it could be arranged that for :: the parens are optional so that

const x  = value::func;

and

const x = value::func();

would be identical and both desugar to

const x = func.bind(value);

@ljharb
Copy link
Member

ljharb commented May 4, 2022

That would be far, far worse. The former should only bind, and the latter should only call, and the mistake made with new where invoking parens are optional should never be repeated.

Using higher-order functions at all is rare; using receiver-sensitive higher-order functions should be almost nonexistent. Just use parens for these cases.

@Haringat
Copy link
Author

Haringat commented May 4, 2022

@ljharb and how would you create parameter bindings with that approach? Say, you want to fix the first argument to a set value and only want the function to be called with the other arguments. Here is an example that comes to mind:

function logValue(prefix, loggable) {
    this.log(prefix + loggable);
}

values.forEach(console::logValue("prefix: "));

@ljharb
Copy link
Member

ljharb commented May 4, 2022

ok so, a few things. First of all, I simply wouldn't do that, because it's a standalone function and shouldn't use this at all. However, if I had to for some reason, I'd do values.forEach(logValue.bind(console, 'prefix: ')). iow, this syntax is explicitly NOT intended to allow you to bind arguments, only the receiver.

@Haringat
Copy link
Author

Haringat commented May 4, 2022

Where does it state that the syntax was explicitly not intended for that?

@ljharb
Copy link
Member

ljharb commented May 4, 2022

The entire readme discusses the receiver and doesn't mention arguments, for seven years, as does the strawman linked in the readme, via archive.org which dates back many years before that.

@Haringat
Copy link
Author

Haringat commented May 4, 2022

"it does not state anything about that" is not the same as "it is explicitly not intended for that". Explicit would mean that it actually states somewhere that this is not supposed to work.

@ljharb
Copy link
Member

ljharb commented May 4, 2022

Fair enough, it doesn’t state it. But through every discussion of it I’ve been present for, it was explicitly the purpose.

@Pro2stinger
Copy link

This isn't needed. Instead of value:::func(arguments) this could be used value::func()(arguments).

@Haringat
Copy link
Author

@Pro2stinger this would require func to always return a bound function. This would be a hassle to write, at which point using Function.prototype.call would actually be more convenient.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants