Named Paramters
What about:
foo({ bar: 5 })
function foo ({ baz, bak, bar }) {
console.log(bar)
}
Or is there anything else you are considering or something I am missing.
If we really need this, you may want to use colon to replace the assignment operator in your example. foo(bar: 5)
No, I didn't mean simulating them via an object literal. I mean actual named parameters like in Python or C# for example.
Are there any plans to peruse that and if so what is the status?
- It would break backwards compatibility:
var bar = 1;
if(baz(bar))foo(bar = 5);
console.log(bar); // 5 in some cases
- Code with this feature will be broken after minification.
(A minifier that breaks your code is a broken minifier and should never be a valid argument for these cases)
It won't break if Gary Guo's idea is used, i.e. use a colon instead of an equal.
So you propose don't compress arguments of all functions? :)
I think my original post might have been confusing so allow me to clarify.
I'm not suggesting to add named parameters to the language, I did not intend to start a discussion about named parameters' merits vs passing an object literal (I thing Axel had a blog about that a while ago).
What I'm interested in is *where the **is *TC standing in this regard.
- Are there any proposals currently under work (TC's GitHub suggests no)?
- Were there proposals in the past that were rejected or abandoned?
- Was there discussion about named parameters in the language before?
Since I sent the original email I've found lukescott/es-named-arguments which isn't a proposal yet but looks pretty new, so I'll just cc Luke and see if he can update us all (although it looks like his proposal ties it to type hints) :)
On Jul 12, 2015, at 2:48 AM, Benjamin Gruenbaum <benjamingr at gmail.com<mailto:benjamingr at gmail.com>> wrote:
I think my original post might have been confusing so allow me to clarify.
I'm not suggesting to add named parameters to the language, I did not intend to start a discussion about named parameters' merits vs passing an object literal (I thing Axel had a blog about that a while ago).
What I'm interested in is where the is TC standing in this regard.
- Are there any proposals currently under work (TC's GitHub suggests no)?
- Were there proposals in the past that were rejected or abandoned?
- Was there discussion about named parameters in the language before?
Since I sent the original email I've found lukescott/es-named-arguments which isn't a proposal yet but looks pretty new, so I'll just cc Luke and see if he can update us all (although it looks like his proposal ties it to type hints) :)
At the moment my focus has been on type hints, although I've been rather busy at work. I have a few tasks to finish on that :).
The named parameters example is one rational why a space should be used for type hints instead of a colon. I had brought up named parameters on the list at some point and some people suggested destructuring instead. Personally I'd rather be able to name parameters without creating an object.
The status of the repo is it's currently a concept.
Luke
Thanks for the clarification.
On Jul 12, 2015, at 1:48 AM, Benjamin Gruenbaum wrote:
I think my original post might have been confusing so allow me to clarify.
I'm not suggesting to add named parameters to the language, I did not intend to start a discussion about named parameters' merits vs passing an object literal (I thing Axel had a blog about that a while ago).
What I'm interested in is where the is TC standing in this regard.
- Are there any proposals currently under work (TC's GitHub suggests no)?
not with TC39, AFAIK
- Were there proposals in the past that were rejected or abandoned?
probably (and informally) but you'd have to search the last 10 years of es-discuss and TC39 meeting notes
- Was there discussion about named parameters in the language before?
Yes, when object destructuring of function parameters was first being discussed. The TC39 consensus was that the option object pattern had already adequately filled that ecological niche so we focused on making sure that parameter destructuring were useful for dealing with them.
Ok, thanks, that clarifies it.
This is extremely for the optional parameters important
function foo (bar, bak=1, qux=2) { }
// here I want bar
to be default, but the quux
take another value
foo(5, qux: 3);
People often suggest object destruction here, but it is then just a workaround. And when the arguments are renamed during the minification, all the labels in function calls can be minified accordingly too.
In fact, it's impossible.
And when the arguments are renamed during the minification, all the labels in function calls can be minified accordingly too.
You can't statically determine which function will be called. Minifier CAN'T know in general case if your $(selector='wow') calls jQuery or some other function at minify time.
So: you can't rely on optional parameters in any CDN-distributed file (because your minifier doesn't know about it's pre-minification identifiers), minifier have to avoid any parameters names clash at any cost.
Possible solution: add gramar explicitly declare optional parameters by keyword to avoid minifaction of their names names.
If we wanted to add named parameters, we would probably have a different name for the named parameter inside the function and outside the function.
function foo(x as y){
}
foo(y = 5);
Or something like that. That said, I'm not convinced we need named parameters, that they justify the additional cost or the overhead, that current solutions like destructing aren't enough and so on. Even if we all agreed that we want named parameters, and we agreed in general lines how it should be done, and we convinced the TC, there would still be a lot of work to actually "decide' they should make it to ES.
So I suggest we close this thread and anyone who feel strongly about including named parameters should work on a concrete proposal :)
Seems everybody is pessimistic about this. But using optional labels
would solve any problem with the minifiers.
// Not minified (Labels are optional, default are the variable names)
function foo (bar = 1, baz = 2, bak = 3) {
console.log(baz);
}
foo (baz: 2);
// Minified
function foo(bar:a=1,baz:b=2,bak:c=3){console.log(b)}
foo(baz:2);
// Explicit Label
function foo (bar = 1, baz: myVar = 2, bak = 3) {
console.log(myVar);
}
foo (baz: 2);
// Minified (same)
function foo(bar:a=1,baz:b=2,bak:c=3){console.log(b)}
foo(baz:2);
And when talking about static analysis, then it is really not always possible to determine the global function variables, but within the scope(s) it shouldn't be the problem. But anyway, the labels will cover all the cases.
Sorry for bothering, if I miss something, Alex
There are a couple of people tossing around named parameter ideas that have
different identifiers than the argument identifier. What is wrong with what
Gary Guo originally said with foo(bar: 5)
, it uses :
for mapping
similar to an object literal, but does not require having contextual
knowledge and breaking changes like =
would; it also does not require
having multiple identifiers for the same variable.
Perhaps I may be wrong here, but having multiple identifiers/bindings to the same variable seems fraught with confusion.
On 12 Jul 2015, at 16:05, Luke Scott <luke at webconnex.com> wrote:
Personally I'd rather be able to name parameters without creating an object.
The intermediate object seem like something that JavaScript engines could eliminate by statically analyzing the code. I’m wondering whether any engine is planning to do that.
Proposal that do not conflict with minimifiers:
- Functions have optional named parameters in any place of argument definition. Optionality is defined by presence of hash character at beginning of parameter name. Optional parameters CAN be placed after rest parameter. These parameters can be accessed by name or by position:
function foo(bar, #qaz, boo) {
return [bar, qaz, boo];
}
foo(1,2,3); // [1,2,3]
foo(#qaz: 3, 4, 1); // [4,3,1] or [4,1,undefined] or throw?
function faz(bar, ...baz, #qoo) {
return [bar, ...baz, qoo];
}
faz(1,2,3,4,#qoo:5); // [1,2,3,4,5]
function print(...toPrint, #delimiter=',', newLine='\n') {
console.log(toPrint.join(delimiter)+newLine);
}
let delimiter = ':';
print(1, 2, 3, 4, 5,#{delimiter}); // prints '1:2:3:4:5\n'
Possible solutions for nonexistant optional argument (eg. foo(#nope:null) ):
- throw (probably the worst solution )
- define
arguments[Symbol.optionals]
object (great for passing optional arguments) - allow syntax for "rest optional parameters"
- ignore
Some problems:
- probably this syntax can not be transpiled in general case
- there is no intuitive behavior for
print (1,2, #delimiter:' ', #{delimiter})
- how will
.apply
work? Third argument with optional arguments?Symbol.optionals
property on second argument (good for seaminglessly passingarguments
, but it doesn't sound like good idea for arrays)?.
Any thoughts?
Could add f{} as sugar for f({}), and make engines optimize f{}? (no positional arguments though)
In principle, I agree with Bucara re: the ({}) syntax. Unfortunately this is often too slow to use in practice. Everyone keeps hoping browser vendors will come up with a way to optimize out small object allocations, but I think that's a pipe dream, because we do have a language that handles fine-grained allocation well: Python.
Python combines reference counting with a cyclic garbage collector. This allows it to amortize the GC cost; most objects (especially small use cases like this one) are destroyed by reference counting. There is, however, a downside: speed. In the case of JS, if one is careful, makes use of object caches and thus manually controls his memory use, one can virtually eliminate the overhead from traditional collectors. One cannot avoid the overhead from reference counting in Python, however.
Collecting many small, heap-allocated objects is just a hard problem to solve, and will always have costs. In the end, I think we will have to find some way for garbage-collected languages to accommodate some sort of stack allocation. There are languages that experiment with them (one of my old college professors wrote a really cool one), but the idea is still relatively undeveloped.
Joe
Engines could inline and infer lifetimes, use stack allocation when possible, etc. Kinda like how LuaJIT is so fast.
Just because they don't yet doesn't mean we should hold back features which would work better if they did.
Plus, you don't /need/ to use "garbage collectible objects" for it. In theory (and in practice) your internal bytecode could have something like this:
function f(x) { return x.y; }
FUNCTION "f" ARG "x" NOGC ; = basically doesn't have to be a "GC object" RET x.y
f({y=3})
SET (temp1) {y=3} NOGC CALL "f" (temp1) FREE (temp1)
You know f takes a NOGC argument, you can create a NOGC object. You could even inline both the call and the object access, actually.
Hey, I wasn't able to find information about the current status of a named parameters propsosal:
Is this being considered? Was it decided for/against? Anyone working on it?