18
$\begingroup$

In R, one can use ... to pass arguments down to another function. For example

fun <- function(arg1, ...){
  print(arg1)
  subfun(...)
}

subfun <- function(mex){
  print(mex)
}

fun(1, "passed down")

Is there a similar construct in Mathematica? In particular I would like to pass down the attribute WorkingPrecision.

$\endgroup$
15
$\begingroup$

Are you looking for implementing option handling by any chance?

Here's a small demonstration of implementing the WorkingPrecision option for function fun, giving it a default value, and always passing it down to subfun.

Options[fun] = {WorkingPrecision -> MachinePrecision}

(* ==> {WorkingPrecision -> MachinePrecision} *)

fun[arg1_, OptionsPattern[]] := 
 subfun[arg1, WorkingPrecision -> OptionValue[WorkingPrecision]]

fun[1]

(* ==> subfun[1, WorkingPrecision -> MachinePrecision] *)

fun[1, WorkingPrecision -> 10]

(* ==> subfun[1, WorkingPrecision -> 10] *)

If you need to pass down every option, then @Mr.Wizard's solution is the right one. To restrict it to options only (expressions of the form name -> value), use

ClearAll[fun]
fun[arg_, opt: OptionsPattern[]] := subfun[arg, opt]

fun[1, WorkingPrecision -> 10, someOptions -> "value"]

(* ==> subfun[1, WorkingPrecision -> 10, someOptions -> "value"] *)
$\endgroup$
  • $\begingroup$ +1 for doing what I was too lazy to (until the OP clarifies the question). $\endgroup$ – Mr.Wizard Feb 17 '12 at 9:40
  • $\begingroup$ @Szabolcs is there a way to pass all declared options of one function to a sub function without having to type it out? If you have three options, it already is quite verbose. $\endgroup$ – SumNeuron Mar 23 '17 at 15:05
  • 1
    $\begingroup$ @SumNeuron myPlot[arg_, opt : OptionsPattern[]] := Graphics[{Circle[]}, FilterRules[{opt}, Options[Graphics]]]. With some functions you may need to precede FilterRule with Sequence @@. $\endgroup$ – Szabolcs Mar 23 '17 at 15:42
  • $\begingroup$ @Szabolcs just to clarify, will that pass down the default arguments or the set arguments as well? $\endgroup$ – SumNeuron Mar 23 '17 at 15:44
  • $\begingroup$ @SumNeuron Only explicitly set arguments. You want the default ones for myPlot (which may be different form the default for Graphics)? $\endgroup$ – Szabolcs Mar 23 '17 at 15:46
13
$\begingroup$

Both the previous examples are perfect if you know explicitly what option you want to pass.

In the more general case you may want to give none, one, or several of a compound set of options to more than one function chosen from a predefined set of functions.

You may even want to give a function as an argument , or option, to a function which can then utilise options given in the primary function call.

Hopefully the example below shows how to do this for built in and user defined functions, it makes use of OptionValue to access option values and FilterRules to ensure that only valid options are passed to any function.

Clear[f, ff, fff];

(* ff, a function to do something, with a parameter *)
Options[ff] = {Squared -> False};
ff[x_, OptionsPattern[]] := If[OptionValue@Squared, x x, x];

(* fff, another function to do something, with a different parameter *)
Options[fff] = {Cubed -> False};
fff[x_, OptionsPattern[]] := If[OptionValue@Cubed, x x x, x];

(* A set of functions you would like your function to be able to handle options for *)
myFuncs = {ff, fff, Plot};

(* Gather together the options from the set of functions you want your function to support, 
plus the options for your own function itself  *)
Options[f] = 
  Flatten[{Flatten[Options /@ myFuncs, 1], myOpt1 -> 7, 
    aFunction -> ff}, 1];


(* f,  a function which has it's own options and can accept an arbitrary function 
and associated options from the set of those functions who's options it 
supports and returns some elements based on those options *)
f[p1_, func_, opts : OptionsPattern[]] := Module[{p, q, r},

  (* Utilise the function's own, explicitly defined option, myOpt1 and calls a function, 
which was passed as a parameter, along with it's valid options. 
This is achieved using FilterRules  *)
  p = OptionValue[myOpt1] func[p1, FilterRules[{opts}, Options[func]]];

  (* Call a function, passed as an option and any associted options it may 
  have which were passed into this function *)
  q = OptionValue[aFunction][p1, 
    FilterRules[{opts}, Options[OptionValue[aFunction]]]];

  (* Call Plot and filter any options given to this function which are supported by plot *)
  r = Plot[
    ff[x, FilterRules[{opts}, Options[OptionValue[aFunction]]]], {x, 
     0, 10}, Evaluate@FilterRules[{opts}, Options[Plot]]] ;

 (* return the computed elements *)
  {p, q, r}
  ]
(* An example function call, with options for ff, fff and Plot  *)

f[5, fff, Frame -> True, Squared -> True, Cubed -> True]
$\endgroup$
  • $\begingroup$ @Mr.Wizard I can't disagree, but I went with the spirit of the posts above, with a light style of commentary. But I thought it perhaps added a greater depth to the solution. $\endgroup$ – image_doctor Mar 28 '12 at 17:57
  • $\begingroup$ Thanks for the code comments. +1 $\endgroup$ – Mr.Wizard Mar 29 '12 at 7:22
  • $\begingroup$ This is VERY helpful! $\endgroup$ – Chen Stats Yu Dec 12 '14 at 16:47
13
$\begingroup$

Here is what I see written, translated as literally as possible:

fun[arg1_, args___] := (
  Print[arg1];
  subfun[args]
)

subfun[mex_] := (
  Print[mex]
)

fun[1, "passed down"]

1

passed down

$\endgroup$
  • $\begingroup$ Beat me to it by a minute, pretty much posting the identical answer! imgur.com/qpy9k $\endgroup$ – David Feb 17 '12 at 8:02
  • 1
    $\begingroup$ Your answer addresses exactly my question, I take it it was enough clear. Thanks for your answer. $\endgroup$ – Ryogi Feb 17 '12 at 18:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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