Use a doble underscore (triple if you want your function to accept no arguments at all):
f[x__] := List[x]
This is an example
f[1]
{1}
f[1,2]
{1,2}
You can specify the type of argument, and you can also have composite data structures like sequences of two element lists, for example.
As for determining the number of argument, in the simple example given above, I'd use the Length of the list of the sequence of arguments given by x
, that is Length[List[x]]
. The following function is declaring narg
to make it local (but you might also use a global variable in order to access it independently from the functions that use it / but you must clarify what you need those values for if you want a sensible example.
f[x__] := Block[{narg},
narg = Length[ List[x] ];
{narg, List[x]}
]
In this toy example we output a list with the number of arguments and a list of the arguments passed to the function.
f[42]
{1, {42}}
f[a,b,c,d,e]
{5, {a,b,c,d,e}}
The number of outputs can be a a little conundrum. For example, in the above example there is one output: a list with two elements. If you consider that "two outputs" you could concoct a way to return that number too by using Length. In any case, if you let your function return the number of output too, you'd return n+1
outputs.
You might at this point define two global variables: $nargin
and $nargout
or even a global stack with those values but... why should you need these values in Mathematica is the key question here.