4
$\begingroup$

I am editing my original question, as I have figured out a method of doing what I want.

Now my question is if there is a more elegant, efficient way to do the following:

Options[f] = {
    Energy -> energy, 
    Temperature -> Func[Energy*Frequency, {Energy, Frequency}], 
    Frequency -> freq
};
f[OptionsPattern[]] := Module[{energy, temperature, frequency},
  energy = OptionValue[Energy];
  frequency = OptionValue[Frequency];
  temperature = If[
    Head[OptionValue[Temperature]] === Func,
    OptionValue[Temperature][[1]] /. Map[# -> OptionValue[#] &,
                     Flatten[{OptionValue[Temperature][[2]]}]],
    OptionValue[Temperature]
    ];
  {
  Energy -> energy,
  Frequency -> frequency, 
  Temperature -> temperature
  }]

Please note that this has the needed generalization to change what options are used as arguments to the passed function or if desired a value (or variable) can be directly inserted as an option.

For this application I have >70 Options (parameters) and I would like to be able to insert (if desired) a function with arguments based on any of the other options, or directly insert a value (if a function "Func" isn't desired.)

Is this more clear?

Thanks again!

$\endgroup$
  • $\begingroup$ Hi and welcome! To make the most of Mma.SE start by taking the tour now. As you receive give back, vote and answer questions, keep the site useful, be kind, correct mistakes and share what you have learned. $\endgroup$ – rhermans Jun 3 '18 at 21:04
  • 2
    $\begingroup$ You shouldn't use fas a function name and as a paramter as well. Use another symbol for the f inside your function. I would also suggest that using strings for your option names may be safer (i.e. "TemperatureFunction" instead of the plain TemperatureFunction) (see e.g. Why are some option values symbols, other strings?. $\endgroup$ – MarcoB Jun 3 '18 at 21:17
  • $\begingroup$ Thanks for the response. Please re-read my original question as I have completely changed it. Hopefully, it is more clear now. $\endgroup$ – M. Decker Jun 4 '18 at 0:18
  • $\begingroup$ @M.Decker I have proposed a solution in an answer below. Is that more along the lines of what you seek? $\endgroup$ – MarcoB Jun 4 '18 at 21:14
4
$\begingroup$

Apparently, the only problem was that you scoped f by Module so that OptionValue had a hard time to find the default values for f. (Option stores Option[f] within f, not as DownValue of Option.)

The following should work without any problems.

Options[f] = {
   Energy -> 25,
   Frequency -> 60,
   TemperatureFunction -> 
    Function[{Energy, Frequency}, Energy*Frequency^2]
   };

f[x_, OptionsPattern[]] := Module[{en, freq, tempFunction},
  en = OptionValue[Energy];
  freq = OptionValue[Frequency];
  tempFunction = OptionValue[TemperatureFunction];
  (* **Missing Necessary Code***)
  x*tempFunction[en, freq]
  ]
| improve this answer | |
$\endgroup$
  • $\begingroup$ Thanks for the response. I have edited my question to be more clear on the desired capability I am seeking. I now have a solution, but I am wondering if there is a more elegant (straight forward and efficient) solution. Thanks again. $\endgroup$ – M. Decker Jun 4 '18 at 0:19
3
$\begingroup$

I mentioned in the comments that I find it advantageous to use strings as the names of my user-defined options. In this case, I think it may work for your problem as well. Here is a sample idea:

ClearAll[f]

Options[f] = {
   "Energy" -> energy,
   "Temperature" -> "Energy" "Frequency",
   "Frequency" -> freq
   };

f[OptionsPattern[]] := Module[
  {energy, temperature, frequency},
  energy = OptionValue["Energy"];
  frequency = OptionValue["Frequency"];
  temperature = With[{tempopt = OptionValue["Temperature"]},
    If[NumberQ@tempopt,
      tempopt,
      tempopt /. Cases[tempopt, a_String :> (a -> OptionValue[a]), Infinity]
    ]
   ]
 ]

So now you can pass a "template" to your function, using the names of the other options / parameters as placeholders for their values (you will just have to be careful not to generate recursive definitions upon function call). For instance:

f["Energy" -> aNumber, "Temperature" -> 2 Exp["Energy"] + Log["Frequency"]]

(* Out: 2 E^aNumber + Log[freq] *)

or:

f["Energy" -> 4, "Temperature" -> "Energy" "Frequency"^2]

(* Out: 4 freq^2 *)
| improve this answer | |
$\endgroup$
  • $\begingroup$ I will take a look at this. I would rather not require quotes, but if it end up speeding up calculated results, I'll go with it. Thanks. $\endgroup$ – M. Decker Jun 6 '18 at 22:03

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.