cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
JMP Wish List

We want to hear your ideas for improving JMP software.

  1. Search: Please search for an existing idea first before submitting a new idea.
  2. Submit: Post your new idea using the Suggest an Idea button. Please submit one actionable idea per post rather than a single post with multiple ideas.
  3. Kudo & Comment Kudo ideas you like, and comment to add to an idea.
  4. Subscribe: Follow the status of ideas you like. Refer to status definitions to understand where an idea is in its lifecycle. (You are automatically subscribed to ideas you've submitted or commented on.)

We consider several factors when looking for what ideas to add to JMP. This includes what will have the greatest benefit to our customers based on scope, needs and current resources. Product ideas help us decide what features to work on next. Additionally, we often look to ideas for inspiration on how to add value to developments already in our pipeline or enhancements to new or existing features.

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

//instead of having to do 
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.  

15 Comments
gzmorgan0
Super User (Alumni)

@vince_faller 

 

Cool example. Thanks for Sharing. Typo correction

show(f(2, {y=14})); // 36 not 33

 

hogi
Level XI

How are the standard Jmp functions defined,

- such that close accepts an supplementary argument noSave.

- such that add column accepts the expression Formula(...) at any position within (...)

dt << New Column( "X", Formula( row() ) );

Instead of 

f(2, {y=14})

could 

f(2, y(14))

be the way how it should look like?

Craige_Hales
Super User

The internal functions are built in C++, not JSL. The user functions (in JSL) are interpreted by other C++ code that chooses how to  turn arguments into parameters (where the arguments to a function are the external values passed in and the function's parameters are the internal variable names that refer to the values.)

A function like sin(A), written in C++, looks something like

ExpressionPointer sin( ExpressionPointer E) {
   double value = evaluateExpression( E );
   double answer = sin( value );
   return makeExpression( answer );
}

The expr() function in JSL, where the function just returns its argument without studying it, looks something like

ExpressionPointer expr( ExpressionPtr E ) {
   return E;
}

That seem useless at first glance, but it allows the assignment operator to evaluate the right-hand-side of

ex = expr( a + b );

and store an expression tree into ex rather than the result of a+b. A more interesting example is the head(a+b) operator.

ExpressionPointer head( ExpressionPointer E ) {
   return MakeExpression( E->child );
}

That's a crude approximation of the idea: an expression tree for a+b has a root, +, which has two children, a and b.  E->child is getting the root, +, and returning that as an expression with no children.

The JMP developers made a decision to hide that complexity in the JSL user written functions to make the 99% use cases easy to write. Most of the languages I'm familiar with don't have expressions that can be manipulated (Snobol does, sort of, and that explains JMP's patmatch() function...) Using a list is a reasonable approach to sending an expression to a function; the list is evaluated...to the same list. The function is working on a copy of the list.

 

Status changed to: Acknowledged
 
hogi
Level XI

The trick with the list is very useful.
Actually, evaluating the list is not really needed to access the variables.

One can scan the list and search for the right name. either by a for each loop or via Extract Expr.

 

Names default to here(1);

get = Function ({var}, Eval(Eval Expr(Arg(Extract Expr(kwarg,  Expr(Name Expr(var)) = wild()),2))));

f = function({x, kwargs={}},
	{DEFAULT LOCAL}, 
	print(get(Expr(z)));
);

f(1, {z=2});