Creating custom functions with multiple arguments

The original question asked how to do something like the following in Mathematica

function_name < - function (arg1, arg2, ..., argn) {
  routine 1 
  routine 2 
  routine 3 
  ... 
  Output to be returned}

So, yes! You could do something like this:

functionName[arg1_, arg2_, arg3_ (* '_' following a name identifies a function argument *)] := 
 Module[{local1, local2, local3 (* Local variables *)},

  local1 = Join[arg1, {a, a, c, a, e, b, d}];
  local2 = Sort /@ local1;
  local3 = local2 + arg1 * arg3; 

  {local1, local2, local3} (* Output to be returned *)
  ]

So again, yes you can define a function that has:

  • any number of arguments,
  • any number of local variables,
  • routines that set local variables, and
  • return any, all, or any combination of the local variables.

Note one can also define local functions inside a function then use them just as you would any other. A simple if kind of silly example follows:

functionName[arg1,arg2]:= 
  Module[{loca1,local2,localFunction}, 
  localFunction[localAgr1_,localArg2_]:=localAgr1^localArg2;
  local1=localFunction[arg1,arg2];
  local2=local1 * 2;
  local2]

Simply put Mathematica gives you extensive flexibility.

As others have commented look up functions, Module, Block, and functional programming. It will reward you with precise, elegant, and powerful code.


You've already had a lot of feedback suggesting that some time with a basic introduction to programming would be useful. I'm going to provide an answer anyway, in the hope of providing a “teachable moment” for other beginning Mathematica users.

My first comment is that the code you have posted is not complete: the two outermost For loops do not have closing square brackets. This will be clear from the pink syntax highlighting in the Mathematica front end. Even after I fixed this and a few other things up, your version of the code doesn’t actually return anything. The definition of a function v[z_] isn't used elsewhere in your code, so it is hard to work out what you are trying to do. And since you are using KSubsets, don’t forget you need to evaluate the following first.

Needs["Combinatorica`"]

My second comment echoes those of others: you almost never need loops in Mathematica. There is usually another, more efficient and concise way. (The exception is if you are going to compile the code using a C compiler, but you are not at that stage.) István’s suggestion to explore the functional-style tag is a good one. In particular, have a look at this summary of alternatives to looping constructions.

Now, to the specifics of your code. The commenters who suggested wrapping your multiple statements in Module were exactly right. This is a scoping construct which will allow you to localize your intermediate variables so their definitions don’t leak out to affect other calculations. You then don’t need that Clear statement. The last line is indeed returned, as long as there is no semicolon suppressing output.

I am now going to go through some obvious issues with the code. Take this line:

For[i = 0, i < Length[t], i++;  t[[i]] = Sort[ t[[i]] ] ]

What you mean is, “I want every sublist in t to be sorted”. You would be much better off just using Map, which “maps” a function onto each element of a list. The shorthand version of Map is /@, so:

t = Sort /@ t

Here’s another example.

For[j = -1, j < k, j++; t = Join[t, {j}]

All this is doing is creating a vector from -1 to k. So just kill that loop and try:

t = Range[-1,k-1]

Another issue in your code is that, at the point that you invoke KSubsets, you are outside the two inner For loops. So $n = k$, and you are finding KSubsets of length zero, i.e. empty sets.

A final point I’d make is that you are defining variables like n and k that are just mirroring the iterators in your For loops. This is a waste of time in a language like Mathematica and just makes your code harder to read.

Making all the above changes results in something like the following:

KenjosFunction[kk_Integer?Positive] := 
 Module[{r, v, w, p, q, z, x, n, k, result = {}},
  For[n = 0, n < kk, n++;
   For[k = 0, k < n, k++;
    For[i = 0, i < (n - k), i++;
     result = 
      Join[result, 
       Union[Sort /@ KSubsets[Range[-1, k - 1], (n - k)]]]];
    ]];
  result 
   ]

There are still three nested For loops which I haven’t cleaned up, but it is much cleaner and easier to read. It also actually gives a result, though I have no idea if it is the one you want:

KenjosFunction[4]
(* {{-1}, {0}, {-1, 0}, {-1, 0}, {-1}, {0}, {1}, {-1, 0}, {-1, 1}, {0, 
  1}, {-1, 0}, {-1, 1}, {0, 1}, {-1}, {0}, {1}, {2}} *)

Further simplifications you could consider, depending on your real code, includ eliminating the For loops by defining a single nested Table and using Flatten to get the right dimensions. I leave this as an exercise for you.