Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Previously, I've defined a function with a variable number of arguments with the following method.

x = {x1, x2, x3};
f1 = Function[
  Evaluate[x],
  x + 1 //
  Evaluate
];
f1 @@ x
Output: {1 + x1, 1 + x2, 1 + x3}

Also, I've defined a function that returned a function as follows.

g[x_] := Function[
  {z},
  x + z //
  Evaluate
];
f2 = g @@ {z};
f2 @@ {x1}
Output: x1 + z

But when I attempt to put these ideas together, I have an issue. The hang-up seems to be in passing the argument of the first function to the argument of the second. Note that in our second example, above, we weren't passing x as an argument to the inner function. However, this is exactly what we want to do:

h[x_] := Function[
  Evaluate[x],
  x + 1 //
  Evaluate
];
f3 = h @@ x;
f3 @@ x
Output: h[x1, x2, x3][x1, x2, x3]

The desired output is {1 + x1, 1 + x2, 1 + x3}. My motivation for writing such a function is to bury it in a package.

share|improve this question
    
Very closely related question (may be even a duplicate). –  Leonid Shifrin May 7 at 11:36

1 Answer 1

up vote 2 down vote accepted
x = {x1, x2, x3};

h[x_] := Function[Evaluate[x], x + 1 // Evaluate];
f3 = h@x
f3 @@ x

(* {1 + x1, 1 + x2, 1 + x3} *)
share|improve this answer
    
thanks! Can you explain why this works? –  Rico Picone May 7 at 4:59
    
@RicoPicone: When you Apply (@@), think of it as basically turning your list into the arguments to the function. So in your example, you're trying to apply a function of one argument to three, so since it doesn't match, it returns unevaluated. In your next step, you're applying that to the list, giving you the h[x1, x2, x3][x1, x2, x3] nonsense. By changing your first operation to just @ (function invocation), the whole list is passed as the argument, allowing a function of three arguments to be returned, so the following Apply matches it, presto. If not clear, comment! –  rasher May 7 at 5:09
    
Thanks, that clears it up. I had always been unclear on the difference between @ and @@. –  Rico Picone May 7 at 5:46
    
The problem with this solution is that it will leak evaluation in cases where x1, etc. have prior values. But the real problem is how the question is formulated, because it is rather hard to partially evaluate the input to a list of symbols but not further. Put another way, what is asked for is a macro rather than a function, but Mathematica has no read-time, and so writing this sort of macros is hard, since macro-expansion gets mixed with evaluation. –  Leonid Shifrin May 7 at 11:47
2  
@RicoPicone The biggest problem is that you store a list of variables in another variable. If you'd be fine with always supplying it explicitly, then the following modification of Rasher's solution would do: SetAttributes[h, HoldAll]; h[vars:{___Symbol}]:=Block[vars, Block[vars, Function @@ {vars, vars + 1}]]. If you want to store your variable list somewhere, the best thing to do is to store them in some HoldAll / HoldAllComplete-attributes-carrying container (e.g. Hold[]), and then redefine h to work as h[Hold[sym___Symbol]]:=.... Otherwise, it gets harder. –  Leonid Shifrin May 7 at 19:51

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.