5

Regarding my recent question on using a default value for a function argument when a pattern was not met yielded some interesting answers, but the general consensus was "Yes this can be done, but there are better options."

Assuming the same conditions that certain function arguments (rt and pt in this case) should default to zero when less than zero, the three main options are as follows:

Downvalues:

func[qi_, dei_, b_, dmin_, rt_, pt_, t_] := 
     func[{qi, dei, b, dmin, Max[0, rt], Max[0, pt], t}]

func[{qi_, dei_, b_, dmin_, rt_, pt_, t_}] := (*do stuff*)

Or...

func[qi_, dei_, b_, dmin_, rt_?Negative, pt_, t_] := func[qi, dei, b, dmin, 0, pt, t]
func[qi_, dei_, b_, dmin_, rt_, pt_?Negative, t_] := func[qi, dei, b, dmin, rt, 0, t]

func[qi_, dei_, b_, dmin_, rt_, pt_, t_] :=(*do stuff*)

Scoping:

func[qi_, dei_, b_, dmin_, rt_, pt_, t_] := Module[{rtt = Max[0,rt], ptt = Max[0,pt]},
   (*do stuff with rtt and ptt instead*) ]

What are the pros and cons of each function definition? Which is the most efficient?

kale
  • 10,922
  • 1
  • 32
  • 69

1 Answers1

5

To start the discussion I'll look at timings. A simplistic test indicates that the DownValues method is somewhat faster, and this agrees with my past experience as well.

f1[a_, b_, c_, d_] := f1[{a, b, Max[c, 0], Max[d, 0]}]
f1[{a_, b_, c_, d_}] := a + b + c + d

f2[a_, b_, c0_, d0_] := With[{c = Max[c0, 0], d = Max[d0, 0]}, a + b + c + d]

a = RandomInteger[{-5, 5}, {1*^6, 4}];

f1 @@@ a // Timing // First
f2 @@@ a // Timing // First

1.872

2.012

Note that I changed Module to With. This should always be faster when it can be used.
For comparison:

f2m[a_, b_, c0_, d0_] := Module[{c = Max[c0, 0], d = Max[d0, 0]}, a + b + c + d]

f2m @@@ a // Timing // First

3.791

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • Wow... I wasn't aware that Module is so much slower! – sebhofer Feb 25 '13 at 18:20
  • @sebhofer Yes, for simple (fast) functions the overhead of Module is significant. With does not let you modify variables. Block is faster than Module but you have to be very careful to avoid unintended consequences. You can often combine e.g. Module outside the definition of the function and Block inside for something reasonably fast. – Mr.Wizard Feb 26 '13 at 01:55