Saturday, 18 January, 2020 UTC


Summary

In Python
I'm sure it's been blogged about a buncha times before but, I couldn't find it, and I had to search too hard to find an example of this. Basically, what I'm trying to do is what Python does in this case, but in JavaScript:
def do_something(arg="notset", **kwargs): print(f"arg='{arg.upper()}'") do_something(arg="peter") do_something(something="else") do_something() 
In Python, the output of all this is:
arg='PETER' arg='NOTSET' arg='NOTSET'
It could also have been implemented in a more verbose way:
def do_something(**kwargs): arg = kwargs.get("arg", "notset") print(f"arg='{arg.upper()}'") 
This more verbose format has the disadvantage that you can't quickly skim it and see and what the default is. That thing (arg = kwargs.get("arg", "notset")) might happen far away deeper in the function, making it hard work to spot the default.
In JavaScript
Here's the equivalent in JavaScript (ES6?):
function doSomething({ arg = "notset", ...kwargs } = {}) { return `arg='${arg.toUpperCase()}'`; } console.log(doSomething({ arg: "peter" })); console.log(doSomething({ something: "else" })); console.log(doSomething()); 
Same output as in Python:
arg='PETER' arg='NOTSET' arg='NOTSET'
Notes
I'm still not convinced I like this syntax. It feels a bit too "hip" and too one-liner'y. But it's also pretty useful.
Mind you, the examples here are contrived because they're so short in terms of the number of arguments used in the function.
A more realistic thing like be a function that lists, upfront, all the possible parameters and for some of them, it wants to point out some defaults. E.g.
function processFolder({ source, destination = "/tmp", quiet = false, verbose = false } = {}) { console.log({ source, destination, quiet, verbose }); // outputs // { source: '/user', destination: '/tmp', quiet: true, verbose: false } } console.log(processFolder({ source: "/user", quiet: true })); 
One could maybe argue that arguments that don't have a default are expected to always be supplied so they can be regular arguments like:
function processFolder(source, { destination = "/tmp", quiet = false, verbose = false } = {}) { console.log({ source, destination, quiet, verbose }); // outputs // { source: '/user', destination: '/tmp', quiet: true, verbose: false } } console.log(processFolder("/user", { quiet: true })); 
But, I quite like keeping all arguments in an object. It makes it easier to write wrapper functions and I find this:
setProfile( "My biography here", false, 193.5, 230, ["anders", "bengt"], "South Carolina" ); 
...harder to read than...
setProfile({ bio: "My biography here", dead: false, height: 193.5, weight: 230, middlenames: ["anders", "bengt"], state: "South Carolina" });