Showing posts with label Function. Show all posts
Showing posts with label Function. Show all posts

Sunday, December 20, 2015

Apply a List of Functions to a Corresponding List of Arguments

Here are two ways to apply a List of functions to a List of arguments. The first method, from Maeder, uses Inner. Note the use of a purely symbolic example to reveal what Inner is doing.

Inner[#@#2&,{f1,f2,f3,f4},{arg1,arg2,arg3,arg4},List]

{f1[arg1],f2[arg2],f3[arg3],f4[arg4]}

In #1@# &, Slot1 (#1 or abbreviated #) pulls an argument from the first List, which are the functions, and Slot2 (#2 where you do need the "2") pulls an argument from the second List, which are the arguments.

If you wanted to apply a second function, g, to the results rather than just listing them, Inner provides for that:

Inner[#@#2&,{f1,f2,f3,f4},{arg1,arg2,arg3,arg4},g]

g[f1[arg1],f2[arg2],f3[arg3],f4[arg4]]

The second method, from my Mathematica teacher Harry Calkins, uses MapThread, which requires wrapping the function List and the argument List together in a List:

(arguments={{a,b,c},{d,e,f},{r,s,t},{u,v,w}});

(functions={3 #&,3+#&,#/2&,Plus@@@Partition[#,2,1,{1,1},#]&});

He gave an example using some built-in functions and structured the functions and arguments in matrices.By enclosing the assignments in parentheses he showed them as matrices without inadvertently making the assignment to the MatrixForm-formatted List.

arguments//MatrixForm
functions//MatrixForm

(results=MapThread[#1@#2&,{functions,arguments}])//MatrixForm


Wednesday, December 2, 2015

The Basics of Slot (#) in Pure Functions

Pure Function, as it's called, such as Function[x, x^2] that yields x2 or the beautiful shorthand, #^2&, is extremely useful in Mathematica:
  1. For one-time functions
  2. As an argument in many functional-style commands such as Map, Nest, Fold, Select, Count, etc
  3. In the extended Postfix style of programming I developed to eliminate hard-to-read nested functions
  4. In predicates including those used for argument type-checking: _?(# <= 1 &)
  5. In the general pattern-matching predicate MatchQ
  6. And the new use in Associations in version 10

Slot must be used with the pure Function operator &. They are designed to be the Head of a function:

#1&[a,b,c]

a

When you use the Postfix style just remember that Postfix causes the ampersand abbreviation for Function to wrap around an entire expression preceding it. Thus it has a low precedence of 90; here are its neighbors:

Precedence/@{Set,Postfix,Colon,Function,TimesBy,Rule}

{40.,70.,80.,90.,100.,120.}

It can be confusing if there are nested used of Function, but using that principle, you can figure it out.

Important: What trips up beginners is using Slot with Mathematica's universal container, List. This doesn't work:

#1&{a,b,c}

{a (#1&),b (#1&),c (#1&)}

There are several solutions. Using Apply (@@) will return a Sequence:

args=##&@@{a,b,c,d}

Sequence[a,b,c,d]

A Sequence is a list designed to be fed to any function:

func@args

func[a,b,c,d]

You can wrap SlotSequence in List so it returns a List:

{##}&[a,b,c,d]

{a,b,c,d}

Here are typical uses with Function as the Head or using Apply. Note that you cannot use negative position numbers with Slot or SlotSequence since that would conflict with using Subtract in pure Functions (like #-2&).

"First" (the default position argument for Slot is 1 so you don't need to specify it with "#1")

#&@@{a,b,c}

a

Return the first two arguments:

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

{1,2}

Return all arguments:  ## is SlotSequence, which returns a Sequence, which is designed to be given to any function as its argument list.

##&[a,b,c,d]

Sequence[a, b, c, d]

{##}&[a,b,c,d]

{a, b, c, d}

##&@@@[a,b,c,d]

{a, b, c, d}

Return the first and fourth arguments:

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

{1,4}

"Rest": Return the 2nd argument to the last:

{##2}&[a,b,c,d]


Sequence[b,c,d]

As of version 10, there is an interesting new usage for Slot with Associations. Slot suffixed with any Key (name) of an Association will automatically return the Value associated with the Key.

cityPopulationAssociation=Association["Tokyo"->"37 million","Jakarta"->"26 million","Seoul"->"17 million","Delhi"->"22 million","Shanghai"->"21 million"];

#Delhi&@cityPopulationAssociation

22 million