7
$\begingroup$

Sorry, I'm just starting to learn mathematica.

I have the following two-argument function:

h[{x_, y_}] := x ^ y

When I do the following:

Map[h, {{1, 2}, {2, 2}, {3, 2}}]

I get the expected output:

{1, 4, 9}

I was wondering what I'm doing wrong with the following rewrite of the above map expression (I want to learn how to use #1 ... #n 's):

 #1 ^ #2 & /@ {{1, 2}, {2, 2}, {3, 2}}

the error messages I'm getting are:

Function::slotn: "Slot number 2 in #1^#2& cannot be filled from (#1^#2&)[{1,2}]"

Function::slotn: "Slot number 2 in #1^#2& cannot be filled from (#1^#2&)[{2,2}]."

Function::slotn: "Slot number 2 in #1^#2& cannot be filled from (#1^#2&)[{3,2}]."

$\endgroup$

4 Answers 4

11
$\begingroup$

If you want to use Map[] that is possible too:

#[[1]]^#[[2]] & /@ {{1, 2}, {2, 2}, {3, 2}}
$\endgroup$
10
  • $\begingroup$ thanks! I do prefer to use Map[] $\endgroup$
    – john peter
    Commented May 9, 2013 at 23:00
  • 1
    $\begingroup$ @johnpeter Why? Apply is really more appropriate here, and you did explicitly say that you want to learn to use #1, #2, ..., #n, which will only be useful if you go with Apply. $\endgroup$
    – Szabolcs
    Commented May 9, 2013 at 23:03
  • 1
    $\begingroup$ i'm just starting to learn. :-) I guess in this particular case, I was trying to learn how to express the same Map expression differently using #'s. Now I understand what I'm doing wrong, and all of the first 3 answers did help me! $\endgroup$
    – john peter
    Commented May 9, 2013 at 23:27
  • $\begingroup$ @Artes I presume you mean worst for execution time? Given that Map[] auto compiles and @@@ doesn't I don't think the streamlined tests on the linked page you gave tell the whole story. Other than that there are conceptual concerns. You could argue for Apply there as well, but one point here is that you never move away from the data as a List by keeping it conceptually simple with Map[]. $\endgroup$
    – SEngstrom
    Commented May 9, 2013 at 23:43
  • $\begingroup$ @SEngstrom If you don't believe, provide your own tests. You'll convince of that. $\endgroup$
    – Artes
    Commented May 9, 2013 at 23:48
12
$\begingroup$

First of all, let's clarify that if you define h as

`h[{x_, y_}] := ...`

then it takes a single argument which is a list of two items. If you define it as

`h[x_, y_] := ...`

then it takes two separate arguments.

#n denotes the nth argument in a pure function. In the function call (#1^#2)& [{2,3}] you are passing the pure function a single argument. #2 won't have a value so you get an error. If you pass it two arguments, everything is fine: (#1^#2)& [2, 3]

Starting with a list of two items, such as {2,3}, you can use Apply to pass these two items to a function:

Apply[#1^#2 &, {2,3}]

An alternate notation for this is #1^#2 & @@ {2,3}.

You can also Apply at level 1. Check the docs details.

Apply[f, {{1,2}, {3,4}, {4,5}}, {1}]

(* ==> {f[1,2], f[3,4], f[4,5]} *)

A shorthand for the above is f @@@ {{1,2}, {3,4}, {4,5}}.

In conclusion, what you want is

#1^#2 & @@@ {{1,2}, {2,2}, {3,4}}
$\endgroup$
3
  • $\begingroup$ Apply at level one needs to be explicit if you don't use @@@ notation: Apply[f, {{1, 2}, {3, 4}, {4, 5}}, {1}] $\endgroup$
    – SEngstrom
    Commented May 9, 2013 at 23:07
  • $\begingroup$ @SEngstrom Thanks! That was a typo. $\endgroup$
    – Szabolcs
    Commented May 9, 2013 at 23:15
  • 2
    $\begingroup$ If one wants to avoid Slot[]: Power @@@ {{1, 2}, {2, 2}, {3, 4}} (i.e. what amr did). $\endgroup$ Commented May 10, 2013 at 2:46
9
$\begingroup$

For educational purposes, here's a couple other ways to do this:

Power @@@ {{1, 2}, {2, 2}, {3, 2}}

Power[Sequence @@ #] & /@ {{1, 2}, {2, 2}, {3, 2}}

Cases[{{1, 2}, {2, 2}, {3, 2}}, List[x__] :> Power[x]]

# /. List -> Power & /@ {{1, 2}, {2, 2}, {3, 2}}

Replace[{{1, 2}, {2, 2}, {3, 2}}, List -> Power, {2}, Heads -> True]

Note that this kind of head replacement is essentially what @@@ is doing, though @@@ does it specifically at level 1.

MapThread[Power, Transpose[{{1, 2}, {2, 2}, {3, 2}}]]

Power itself threads over lists:

{bases, exponents} = Transpose[{{1, 2}, {2, 2}, {3, 2}}]
bases^exponents

Your functions aren't so awesome:

{bases, exponents} = Transpose[{{1, 2}, {2, 2}, {3, 2}}]
(op[#1, #2] &)[bases, exponents]

You can make them awesome, SetAttributes method:

SetAttributes[f, Listable];
f[a_, b_] := op[a, b];

{bases, exponents} = Transpose[{{1, 2}, {2, 2}, {3, 2}}]
f[bases, exponents]

Thread method:

{bases, exponents} = Transpose[{{1, 2}, {2, 2}, {3, 2}}]
Thread[(op[#1, #2] &)[bases, exponents]]

Third argument to Function method:

{bases, exponents} = Transpose[{{1, 2}, {2, 2}, {3, 2}}]
Function[{a, b}, op[a, b], Listable][bases, exponents]
$\endgroup$
1
6
$\begingroup$

You should use Apply (at the level 1 (@@@)) rather than Map, in terms of a pure function as you looking for:

#1^#2 & @@@ {{1, 2}, {2, 2}, {3, 2}}
{1, 4, 9}

Instead of a pure function #1^#2 & one can simply write built-in Power. Your h function takes only one argument i.e. a two-element list, while the second one (a pure function) has two arguments, so that's why you need Apply instead of Map.

There is another way which sometimes appears even faster (not for Power but for Times and Plus)

#1^#2 & @@ # & /@ {{1, 2}, {2, 2}, {3, 2}}

Similarly here one can use Power instead of #1^#2 &. Take a look at a related question on stackoverflow How to remove the extra {} when Mapping a function to a list. One of the answers contains interesting benchmarks for the both methods and you can learn there that the canonical approach @@@ is roughly 3 times faster for Power, while for Times and Plus the second one is ~4 times faster ( due to autocompilation of Map etc.).

$\endgroup$
2
  • $\begingroup$ That looks like a bit of cursing before the data comes around :) $\endgroup$
    – SEngstrom
    Commented May 9, 2013 at 23:12
  • $\begingroup$ @johnpeter also keep in mind that all the operators in mathematica have a FullForm representation (even operators you might not expect would have such a thing), and that you can just do, for example, Power @@@ {{1, 2}, {2, 2}, {3, 2}}. Try FullForm[HoldForm[out = #1^#2 & @@@ {{1, 2}, {2, 2}, {3, 2}}]] to see what I'm talking about. $\endgroup$
    – amr
    Commented May 9, 2013 at 23:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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