10
$\begingroup$

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.

$\endgroup$
10
  • 12
    $\begingroup$ "Are there other, simpler techniques?" — yes: f@@p :) $\endgroup$
    – rm -rf
    Commented Mar 12, 2013 at 19:37
  • 2
    $\begingroup$ reference.wolfram.com/mathematica/ref/Apply.html $\endgroup$ Commented Mar 12, 2013 at 19:39
  • 9
    $\begingroup$ "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. $\endgroup$ Commented Mar 12, 2013 at 19:57
  • 1
    $\begingroup$ I think that my explanation here, which is just 3 lines, is more or less all there is to it. $\endgroup$ Commented Mar 12, 2013 at 20:06
  • $\begingroup$ @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." $\endgroup$
    – murray
    Commented Mar 13, 2013 at 1:06

4 Answers 4

10
$\begingroup$

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
$\endgroup$
5
  • $\begingroup$ Apologies rm -rf. Apparently I was typing and checking my answer in Mathematica while you supplied f@@p in the comments above. $\endgroup$ Commented Mar 12, 2013 at 19:49
  • $\begingroup$ 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!) $\endgroup$
    – rm -rf
    Commented Mar 12, 2013 at 19:52
  • 5
    $\begingroup$ Why are you constructing a pure function at all? It seems to have no purpose. $\endgroup$
    – Szabolcs
    Commented Mar 12, 2013 at 21:00
  • $\begingroup$ @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. :) $\endgroup$ Commented Mar 13, 2013 at 18:24
  • 4
    $\begingroup$ @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}]. $\endgroup$
    – Szabolcs
    Commented Mar 13, 2013 at 19:40
12
$\begingroup$

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} *)
$\endgroup$
2
  • $\begingroup$ 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. $\endgroup$
    – murray
    Commented Mar 13, 2013 at 3:42
  • $\begingroup$ @murray you are correct, but there are few alternatives. $\endgroup$
    – rcollyer
    Commented Mar 13, 2013 at 3:48
2
$\begingroup$

You could use Part:

f[p[[1]], p[[2]]]
(* -16 *)
$\endgroup$
1
  • 1
    $\begingroup$ My aim is to avoid having to pull a "point" variable apart into its constituent entries! $\endgroup$
    – murray
    Commented Mar 13, 2013 at 1:04
2
$\begingroup$

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.

$\endgroup$

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