10

I frequently encounter the situation where I have a function of two real variables defined, e.g.:

f[x_, y_] := 9 - x^2 - y^2

But then I need to feed into f not just two numbers but rather a pair, i.e., a 2-element list, e.g.:

p = {3, 4};
f[p]

How might this be done simply -- without having to make a separate definition

f[{x_, y_}] := f[x, y] 

Naively I used to expect that the following would work:

f[Sequence[p]]

But it doesn't. What does work, though, is:

f[Sequence @@ p]

Are there other, simpler techniques?

I bring this up as an advocate for relatively new users of Mathematica, because I think Sequence along with Apply is much too sophisticated for them!

Note: The root cause is the typical "abuse of notation" in math, where a "function of two real variables" is really a function of ordered pairs of reals but the notation $f(x, y)$ obscures that.

LCarvalho
  • 9,233
  • 4
  • 40
  • 96
murray
  • 11,888
  • 2
  • 26
  • 50
  • 12
    "Are there other, simpler techniques?" — yes: f@@p :) – rm -rf Mar 12 '13 at 19:37
  • 2
    http://reference.wolfram.com/mathematica/ref/Apply.html – Vitaliy Kaurov Mar 12 '13 at 19:39
  • 9
    "so Sequence along with Apply is much too sophisticated for them" - but here is a problem: what you request is not quite a trivial manipulation, and Apply and Sequence are exactly the tools. I can imagine that one may be able to find some twisted ways out, but I am sure those will be (much) harder to understand than Apply or Sequence. Actually, I don't consider the latter two so hard to comprehend. Apply "eats up" the head it operates on, replacing by another one, while Sequence means "no head", and gives a bare sequence of function's arguments. Not hard, even for a newbie. – Leonid Shifrin Mar 12 '13 at 19:57
  • 1
    I think that my explanation here, which is just 3 lines, is more or less all there is to it. – Leonid Shifrin Mar 12 '13 at 20:06
  • @rm -rf: Again, I'm thinking of the beginner, who would still expect to have to put the argument within brackets, and f@@p goes against that mantra drilled into such beginners, "The argument(s) to a function are enclosed in square brackets." – murray Mar 13 '13 at 01:06
  • @Leonid Shifrin: In my original question, I showed the Sequence@@p trick. However brief the explanation may be, to a beginner this still seem like magic (I know that from experience teaching). It may just be that for beginners the most straightforward approach is the additional definition f[{x_, y_}] := f[x, y]. I was casting about for something else that's almost elementary. – murray Mar 13 '13 at 01:10
  • Let me turn the question around: Suppose the definition started out in the form f[{x_, y_}] := 9 - x^2 - y^2. Then how would you want to tell a beginner to evaluate f[3, 4] -- where there are just two scalar arguments rather than one list argument? – murray Mar 13 '13 at 01:13
  • I don't really know a better way than just put them into a List. But, this is easier to explain than Apply and Sequence, so may be this is then the way to go. – Leonid Shifrin Mar 13 '13 at 01:34
  • If you feel so strongly about this issue, post a contribution to our Community Wiki on new users pitfalls – m_goldberg Mar 13 '13 at 14:19
  • @m_goldberg: not sure it's a "pitfall" so much as an impediment. – murray Mar 14 '13 at 20:26

4 Answers4

12

You can alter your original definition to accept both:

Clear[f]
f[{x_, y_} | PatternSequence[x_, y_]] := 9 - x^2 - y^2
{f[3, 4], f[{3, 4}]}
(* {-16, -16} *)
rcollyer
  • 33,976
  • 7
  • 92
  • 191
  • Not a solution that will be attractive to beginners (PatternSequence is hardly something beginners would know or should see), but it does nicely take care of both situations at the same time. – murray Mar 13 '13 at 03:42
  • @murray you are correct, but there are few alternatives. – rcollyer Mar 13 '13 at 03:48
10

Why not define a pure function and then Apply that to the list?

f[#1, #2] & @@ p

Apply is straightforward to explain to beginners because it simply replaces the head of an expression.

If you want to avoid explaining pure functions, then this seems to do the trick:

f @@ p
TransferOrbit
  • 3,547
  • 13
  • 26
  • Apologies rm -rf. Apparently I was typing and checking my answer in Mathematica while you supplied f@@p in the comments above. – TransferOrbit Mar 12 '13 at 19:49
  • No worries :) I didn't post an answer because such questions usually are closed with a reference to the documentation page and I genuinely thought that the OP just had a temporary brain freeze (you can see from murray's account that he knows Mathematica). However, this is the place where that comment belongs, regardless of what happens to the question :) (also, belated welcome! I don't recall having seen your name before, but you've been around for at least 6 wks!) – rm -rf Mar 12 '13 at 19:52
  • 5
    Why are you constructing a pure function at all? It seems to have no purpose. – Szabolcs Mar 12 '13 at 21:00
  • @Szabolcs That's a very good point about which I'd like to know more. It may be that the pure function has no effect in terms of how Mathematica deals with the expressions; I'm not certain on this point, so if anyone can enlighten me on the details I'd love to know. However, I think that using a pure function may be useful if you're explaining to a beginner how a function gets Applied to its argument. With the more elegant f@@p expression, it seems more obscure how Mathematica deals with the arguments. It was just a thought. :) – TransferOrbit Mar 13 '13 at 18:24
  • 4
    @zentient Technically it does actually make a difference if you use a pure function this way, but not for this particular application. One difference is that f[#1,#2]& discards the 3rd, 4th, etc. arguments (f[##]& wouldn't). Another difference is that if f had the HoldAll or similar attributes, f[#]& would practically discard them. Again, this would only be relevant if it were Apply'd to a Hold[...] or similar, not a List[...]. Another interesting thing to know is that pure functions can have attributes, like this: Function[x, ..., {HoldAll}]. – Szabolcs Mar 13 '13 at 19:40
2

You could use Part:

f[p[[1]], p[[2]]]
(* -16 *)
Mike Z.
  • 661
  • 4
  • 7
2

This Q&A is considered canonical and is used as a base for marking others [duplicate] so answers should cover the topic best.


It is another one way then: (thanks to rm -rf)

l = {a, b, c, s};
Operate[f &, l]
f[a, b, c, s]

but in such simple case f@@l is what I use.

Kuba
  • 136,707
  • 13
  • 279
  • 740