Functions with Variable Number of Input Parameters

Creating a function with variable number of inputs?

Use fprintf with varargin for this:

f = @(varargin) fprintf('var%i= %i\n', [(1:numel(varargin));[varargin{:}]])
f(5,6,7,88)
var1= 5
var2= 6
var3= 7
var4= 88

The format I've used is: 'var%i= %i\n'. This means it will first write var then %i says it should input an integer. Thereafter it should write = followed by a new number: %i and a newline \n.

It will choose the integer in odd positions for var%i and integers in the even positions for the actual number. Since the linear index in MATLAB goes column for column we place the vector [1 2 3 4 5 ...] on top, and the content of the variable in the second row.

By the way: If you actually want it on the format you specified in the question, skip the \n:

f = @(varargin) fprintf('var%i= %i', [(1:numel(varargin));[varargin{:}]])

f(6,12,3,15,5553)
var1= 6var2= 12var3= 3var4= 15var5= 5553

Also, you can change the second %i to floats (%f), doubles (%d) etc.

If you want to use actual variable names var1, var2, var3, ... in your input then I can only say one thing: Don't! It's a horrible idea. Use cells, structs, or anything else than numbered variable names.

Just to be crytsal clear: Don't use the output from this in MATLAB in combination with eval! eval is evil. The Mathworks actually warns you about this in the official documentation!

Function call with variable number of input arguments when number of input arguments is not explicitly known

Couple of helpful points to construct a solution:

  • This post shows you how to construct a Cartesian product between arbitrary arrays using ndgrid.
  • cellfun accepts multiple cell arrays simultaneously, which you can use to index specific elements.
  • You can capture a variable number of arguments from a function using cell arrays, as shown here.

So let's get the inputs to ndgrid from your outermost array:

grids = cellfun(@(x) 1:numel(x), pth, 'UniformOutput', false);

Now you can create an index that contains the product of the grids:

index = cell(1, numel(pth));
[index{:}] = ndgrid(grids{:});

You want to make all the grids into column vectors and concatenate them sideways. The rows of that matrix will represent the Cartesian indices to select the elements of pth at each iteration:

index = cellfun(@(x) x(:), index, 'UniformOutput', false);
index = cat(2, index{:});

If you turn a row of index into a cell array, you can run it in lockstep over pth to select the correct elements and call mintersect on the result.

for i = index'
indices = num2cell(i');
selection = cellfun(@(p, i) p{i}, pth, indices, 'UniformOutput', false);
mintersect(selection{:});
end

This is written under the assumption that pth is a row array. If that is not the case, you can change the first line of the loop to indices = reshape(num2cell(i), size(pth)); for the general case, and simply indices = num2cell(i); for the column case. The key is that the cell from of indices must be the same shape as pth to iterate over it in lockstep. It is already generated to have the same number of elements.

Functions with variable number of input parameters

Advanced features like VARIADIC or even polymorphic input types and dynamic SQL are very powerful. The last chapter in this answer provides an advanced example:

  • Refactor a PL/pgSQL function to return the output of various SELECT queries

But for a simple case like yours, you can just use default values for function parameters. It all depends on exact requirements.

If the columns in question are all defined NOT NULL, this would probably be simpler and faster:

CREATE OR REPLACE FUNCTION update_site(_name      text    -- always required
, _city text DEFAULT NULL
, _telephone integer DEFAULT NULL)
RETURNS integer AS
$func$
BEGIN
IF _city IS NULL AND _telephone IS NULL THEN
RAISE WARNING 'At least one value to update required!';
RETURN; -- nothing to update
END IF;

UPDATE "Sites"
SET "City" = COALESCE(_city, "City")
, "Telephone" = COALESCE(_telephone, "Telephone")
WHERE "SiteName" = _name;
END
$func$ LANGUAGE plpgsql;

Read about default values in the manual!

To avoid naming conflicts between parameters and column names I make it a habit to prefix input parameters with _. That's a matter of taste and style.

  • The first parameter name has no default, since it is required at all times.
  • Other parameters can be omitted.
  • At least one is required, or a WARNING is raised and nothing else happens.
  • The UPDATE will only change columns for given parameters.
  • Can easily be expanded for N parameters.

Function call

Since Postgres 9.5:

The simple way is with positional notation for parameters. This only allows to omit the rightmost parameter(s):

SELECT update_site('foo', 'New York');  -- no telephone

Named notation allows to omit any parameter that has a default value:

SELECT update_site(name => 'foo', _telephone => 123);  -- no city

Both can be combined in mixed notation:

SELECT update_site('foo', _telephone => 123);  -- still no city

In Postgres 9.4 or older, := was used for assignment in the call:

SELECT update_site(name := 'foo', _telephone := 123);
SELECT update_site('foo', _telephone := 123);

Still valid in Postgres 12 for backward compatibility, but rather use the modern notation.

Can a variable number of arguments be passed to a function?

Yes. You can use *args as a non-keyword argument. You will then be able to pass any number of arguments.

def manyArgs(*arg):
print "I was called with", len(arg), "arguments:", arg

>>> manyArgs(1)
I was called with 1 arguments: (1,)
>>> manyArgs(1, 2, 3)
I was called with 3 arguments: (1, 2, 3)

As you can see, Python will unpack the arguments as a single tuple with all the arguments.

For keyword arguments you need to accept those as a separate actual argument, as shown in Skurmedel's answer.

How do i make a function with a variable number of parameters?

First of all Variadic arguments from C are considered a bad practice in C++ and should be avoided.

There are plenty of better C++ solutions which are able to replace this C feature.

Old fashioned std::vector:

std::vector<int> filterPrimes(std::vector<int> a) {
auto end = std::remove_if(a.begin(), a.end(), [](auto x) {
return !isPrime(x)
};
a.remove(end, a.end());
return a;
}

Or std::initializer_list

std::vector<int> filterPrimes(std::initializer_list<int> l) {
std::vector<int> r;
std::copy_if(l.begin(), l.end(), std::back_inserter(r), isPrime);
return r;
}

Or Variadic templates, or template with iterator ranges, or ... .

Function with a variable number of parameters

I think this answers your question.

def _more_data_(*args):
f = open(file,'w')
f.write(str(args[0])+';\n')
return

Or you can do this to write every argument you pass.

def _more_data_(*args):
f = open(file,'w')
for i in range(len(args)):
f.write(args[i])
return

Happy to help : )

Creating a function in R with variable number of arguments,

d <- function(...){
x <- list(...) # THIS WILL BE A LIST STORING EVERYTHING:
sum(...) # Example of inbuilt function
}

d(1,2,3,4,5)

[1] 15

C++ Function with variable number and types of arguments as argument of another function

It is not foolproof, but any possible errors will be caught at compile time (ie. the code will not compile). It should work file, as long as the provided parameters match those of the called function, and a matching << operator exists for each parameter.

template<class Fn, class...Args>
void execute_and_print(Fn fn, Args...args) {
int f[sizeof...(Args)] = { (std::cout << args << ", ", 0)... };
fn(args...);
}

Refer to https://en.cppreference.com/w/cpp/language/parameter_pack. The sizeof... command is actually the number of elements, not their combined size.

Function with variable number of arguments

Yes you can write something like this:

void PrintReport(string header, params int[] numbers)
{
Console.WriteLine(header);
foreach (int number in numbers)
Console.WriteLine(number);
}

Variable number of arguments in C++?

You probably shouldn't, and you can probably do what you want to do in a safer and simpler way. Technically to use variable number of arguments in C you include stdarg.h. From that you'll get the va_list type as well as three functions that operate on it called va_start(), va_arg() and va_end().

#include<stdarg.h>

int maxof(int n_args, ...)
{
va_list ap;
va_start(ap, n_args);
int max = va_arg(ap, int);
for(int i = 2; i <= n_args; i++) {
int a = va_arg(ap, int);
if(a > max) max = a;
}
va_end(ap);
return max;
}

If you ask me, this is a mess. It looks bad, it's unsafe, and it's full of technical details that have nothing to do with what you're conceptually trying to achieve. Instead, consider using overloading or inheritance/polymorphism, builder pattern (as in operator<<() in streams) or default arguments etc. These are all safer: the compiler gets to know more about what you're trying to do so there are more occasions it can stop you before you blow your leg off.



Related Topics



Leave a reply



Submit