Our World Statistics Day conversations have been a great reminder of how much statistics can inform our lives. Do you have an example of how statistics has made a difference in your life? Share your story with the Community!
Choose Language Hide Translation Bar

## Keyword arguments for functions

I would love if in User Defined funcitons we could use keyword arguments in the calls so I can do

``````Names default to here(1);
f = function({x, y=2, z=3},
show(x, y, z);
);
print("What I'd like to do");
f(1, z=2);
//I want it to be 1, 2, 2

f = function({x, kwargs={}},
{DEFAULT LOCAL},
// optional
y = 2;
z = 3;
evallist(kwargs);
show(x, y, z);
);
print("Using List");
f(1, {z=2});``````

Someone mentioned it here, but it was 8 years ago, so figured I'd bring it up again.

### Defect ID: Super User

Your current "kwargs" list solution is a nice interim trick. Super User

Thanks.  It definitely has a few problems. The biggest probably being able to inject any variables into a function and often causes variable collision I'm not careful.

``````Names default to here(1);

f = function({x, kwargs={}},
{DEFAULT LOCAL},
// optional
y = 2;
z = 3;
evallist(kwargs);
show(y);
//even though f2 is default local,
//because it's not explicit in the function it writes to here
f2(1, {b=3, y=5});
show(y);
);

f2 = function({a, kwargs={}},
{DEFAULT LOCAL},
b=2;
c=3;
evallist(kwargs);
show(a, b, c);
);

f(1, {z=2});`````` Staff

This would need a new syntax that wouldn't change existing scripts. Maybe something like your example with a list being passed to a special receiver. Or maybe a new syntax on the caller such as a fake namespace: f(1, arg:z = 2). Super User

Why would a new syntax be required?    Are you saying for calling or for defining?  I think we could define them the same way.

If a function already doesn't use keyword arguments then it would default to positional arguments like it currently does.

Obviously we wouldn't be able to use keyword arguments before it's implemented so I don't see that as breaking scripts.

The function

``````f = function({x, y=2, z=3},
show(x, y, z);
);``````

wouldn't break any other scripts.

and if all previous scripts are using positional arguments anyway then I don't think it would break anything.

But if I there were keyword args that default to positional if no keywords were specified, doing

``f(1, 2, 4);``

wouldn't break anything (I'm guessing). But it would just allow

``f(1, z=4);``

I don't see why it would need a fake namespace (but then again I don't understand how functions work under the hood). Staff

Currently arguments to user functions are evaluated and z=4 is a valid expression, so

``f(1, z=4);``

would evaluate z=4, creating a global z and having a result of 4, and then pass the result to the y argument of f. Super User

Ahh.   So if someone used that syntax (for whatever reason) it would break if they needed a z global later on.  Got it. Staff

Right. Believe it or not, we do try not to break old JSL behaviors, even unlikely ones. Super User

@vince_faller, I still like your proposed kwargs={} solution with a modification.  IMHO Default Local is nice for simple scripting, but is risky for complex scripts.  I recommend managing a list of local variables. Anyway, below is a script that is a modification of your kwargs solution, but uses the syntax, {z,4} vs. z=4 as items in your kwargs list and requires a block of code that can be generic. A function could use a local associative array to assign "keyword" values which would implify the block of code noted below, however, then the individual variable syntax is more cumbersome, instead of a+b it would be something like  aa1[a] + aa1[b], so the exmaple uses lists.

if I had a function with many variables, but for each function call wanted to only change a few, I might use this approach. The key here is that

• no variable gets changed unless it is in the varList, and
• changed values are local.

``````Names Default To Here( 1 );

//simple example
g1 = Function({kwargs={}}, {Default Local},
varList = {a,b,c,d,e,f};
valList = {1,2,3,4,5,6};
For(i=1, i<=nitems(kwargs), i++,
//each item must be a list of 2 values.
If(IsList(kwargs[i]),
Try(valList[loc(varList,kwargs[i])] = kwargs[i])
);
);
Eval( EvalExpr( Expr(varList) = Expr(valList)) ) ;
show(a,b,c,d,e,f);
);

myList = {{a,10},{y,-44},{f,20}};
g1(myList);
// [+] no variable gets changed unless it is in the variable list
// [-]  varList and valList need to be defined
// [-]  lines 7-13 would need to be added to each function, could be a global expression
// [-]  instead of z=4 syntax, {z,4} syntax is required

//------Modification of Vince Faller script

f = function({x, kwargs={}},
{DEFAULT LOCAL},
// optional
varList = {x, y};
valList = {2,3};
For(i=1, i<=nitems(kwargs), i++,
//each item must be a list of 2 values.
If(IsList(kwargs[i]),
Try(valList[loc(varList,kwargs[i])] = kwargs[i])
);
);
Eval( EvalExpr( Expr(varList) = Expr(valList)) ) ;
show(y);
//even though f2 is default local,
//because it's not explicit in the function it writes to here
f2(1, { {b,3}, {y,5}});
show(y);
);

f2 = function({a, kwargs={}},
{DEFAULT LOCAL},
varList= {b,c};
valList = {2,3};
For(i=1, i<=nitems(kwargs), i++,
//each item must be a list of 2 values.
If(IsList(kwargs[i]),
Try(valList[loc(varList,kwargs[i])] = kwargs[i])
);
);
Eval( EvalExpr( Expr(varList) = Expr(valList)) ) ;
show(a, b, c);
);

f(1, {z=2});`````` Super User

@gzmorgan0 My biggest problem with the kwargs list is that it allows anything to be executed. For instance if I want to see all of the locals in a given function.

``````f = function({x, kwargs = {}},
{y = 2, z = 3, a = Expr(y + z)},
evallist(kwargs);
r = x + y + z;
return(r);
);

f(14, {print(namespace("local") << Get Contents)});``````

Which is a security problem for me with encrypted code.

I actually keep things in an associative array and then do an << intersect with a default associative array to check that the passed arguments are valid.

Then I just parse the key value pairs into the function so I don't have to use the array to call them.

I have help functions to do all of this but that brings out its own set of problems.  And it's more cumbersome than I like.

@XanGregg, my bad.  I have a much more narrow field of view on most of these things.