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.

Suppose we have a function f[x, y, z] and we want to get all its variables Sequence[x,y,z], what method can we use then? The only one that I can come up with is like this:

f[x, y, z] /. func_[vars___] -> Sequence[vars]

But it is not very elegant from my point of view. Is there any more suitable method? Thanks!

share|improve this question
1  
How about Sequence @@ f[x, y, z]? –  Fabian Feb 16 '13 at 19:44
    
Yes, this is more concise. Thanks. –  saturasl Feb 16 '13 at 20:38

2 Answers 2

up vote 6 down vote accepted

For one thing Sequence is applied automatically to a raw sequence (such as vars) if no other head is found, therefore:

f[x, y, z] /. _[vars___] :> vars
Sequence[x, y, z]

This is similar to what I have been calling the "injector pattern" and as you can see from that thread it has value in cases where Sequence @@ f[x, y, z] would not avail you, specifically inside symbols that will hold Sequence objects.


It is hard to guess your application from the question but you can also define a function, perhaps with additional conditions or handling of multiple forms of input, such as:

varSeq[expr_] := 
 With[{vars = Variables @ expr}, Sequence @@ vars /; MatchQ[vars, {__Symbol}]]

varSeq[_@vars__Symbol] := vars

Now:

f[x, y, z] // varSeq
Sequence[x, y, z]
(x + y)^2 + 3 z^2 - y z + 7 // varSeq
Sequence[x, y, z]

Incidentally if you like terse coding you can also make use of SlotSequence, short form ##, as in:

## & @@ f[x, y, z]

which is equivalent to Sequence @@ f[x, y, z] in most cases.

share|improve this answer
    
Now there are two more ways to achieve the goal, Thanks! –  saturasl Feb 16 '13 at 20:03
    
@saturasl Thanks for the Accept. In the future consider waiting longer (I like 24 hours) to give everyone a chance to read the question and answer before it appears "concluded." Since you gave the Accept I added a couple of other things to my answer to try to cover other scenarios. –  Mr.Wizard Feb 16 '13 at 20:35
    
Yes, your additional answer together with PlatoManiac's answer makes this thread valueable for reading. –  saturasl Feb 16 '13 at 21:01

Probably irrelevant but I thought you have some function defined in the Global` context and you want to get the list of its variables. If that is the case I came up with this messy solution.

Suppose you have defined a function like the following somewhere in a notebook and the definition for the symbol fun is available to the kernel as well as not Protected. I am defining the following example function using Module but one can also use Block.

Clear[f];
fun[x_, y_, z_] := Module[{val},
   val = RandomReal[1, 3];
   val . {x, y, z}
   ];

{x,y,z}

Then you can get the arguments of fun using the following

((DownValues[fun])[[1]] /. 
RuleDelayed[HoldPattern[a___],b_] :> (Extract[a, 1, Hold] /. Hold[c_[vars___]] :> List@vars))

{x_, y_, z_}

If you want you can easily convert those pattern into Symbol using First /@%.

From the comments a more robust solution came out credit to Mr. Wizard.

Cases[ DownValues[fun], HoldPattern[fun][vars__] :> {vars}, -1 ] /.
Verbatim[Pattern][name_, _] :> name
share|improve this answer
    
Your answer goes deep into the core language, and this is very valueable to me, thanks! –  saturasl Feb 16 '13 at 20:46
    
@saturasl You are welcome. –  PlatoManiac Feb 16 '13 at 20:50
    
Your method as written is not robust in all cases, for example f[x_, y_, z_] /; something := . . .; it also doesn't address multiple definitions. For the simple case it is shorter to write: DownValues[fun][[1, 1]] /. _@_@vars___ :> {vars} –  Mr.Wizard Feb 17 '13 at 0:16
    
@Mr.Wizard you are right! I was sure my solution will not be general. But do think it is possible to have a solution that works for all type of function definition? it will be good to know. –  PlatoManiac Feb 17 '13 at 9:59
1  
(1) I didn't mean to disparage your answer; only to let new users know that it has limitations. (2) I expect there would still be corner cases that would slip through the cracks but something fairly general should be possible; here's a first attempt: Cases[ DownValues[fun], HoldPattern[fun][vars__] :> {vars}, -1 ] /. Verbatim[Pattern][name_, _] :> name –  Mr.Wizard Feb 17 '13 at 11:08

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.