3
$\begingroup$

I'm developing a package, and one of its functions is param, which reads a rather big file and extract one of the parameters in there.

I have a few more functions, say f1 and f2, and so on, whose definitions depend on the value of param. So straightforwardly I could write

param:=param=(*reading files*)
f1:=Switch[param, value1,def11, value2,def12,...]
f2:=Switch[param, value1,def21, value2,def22,...]
...

The advantage is that as soon as any one of the f functions is called, param will be set, so that when I call other f functions, I can save some time by avoiding reading and defining param again. Also, param will only be defined when it is necessary.

However this code is rather cumbersome, because I have to repeat Switch many times, and each of the defs is itself long. A better way could be

Switch[param,
  value1, f1:=def11;f2:=def21;...,
  value2, f1:=def12;f2:=def22;...,
  ...,
];

Now the code is in a more concise style, but the price is that param will be defined when loading the package, and unnecessarily slowing down the loading when none of the f functions are to be called.

My question is that, is there a better way to do the job, that takes both of the advantages that (1) param is only defined when necessary (when the f functions are called), and (2) the f functions can be define concisely in a collective way?

$\endgroup$

2 Answers 2

2
$\begingroup$

A scheme like the following, using conditional definitions, should work. Here Pause[3] is just representative of the actual time-consuming process that loads the value of param in your package:

ClearAll[param, f1]
param := param = (Pause[3]; 1)

f1 := "f1 defined with param = 1" /; param == 1
f1 := "f1 defined with param = 2" /; param == 2

Now we can see that the first execution of f1 will take longer and use the definition corresponding to the previously-loaded value of param:

AbsoluteTiming[f1]
(* {3.01633, "f1 defined with param = 1"} *)

AbsoluteTiming[f1]
(* {0.0000174, "f1 defined with param = 1"} *)

If, for some reason, the value of param changes, then the other function definition will be used:

param = 2;

AbsoluteTiming[f1]
(* {7.1*10^-6, "f1 defined with param = 2"} *)
$\endgroup$
2
  • $\begingroup$ Thanks! Is there any advantage of using Condition over Switch (the first implementation in the question)? $\endgroup$
    – H. Zhou
    Aug 5 at 15:10
  • $\begingroup$ @H.Zhou To me, Condition results in cleaner and more readable code that fulfills the requirements you had set out. $\endgroup$
    – MarcoB
    Aug 5 at 15:13
2
$\begingroup$

There are several considerations here, and I'm not sure what your priorities are. Do you want to be able to re-execute the code that sets param? Do you want to be able to handle the situation when param hasn't been defined/initialized? And so on...

I tend to avoid magic side effects, and instead make everything explicit, and then introduce the mappings/conditions on top of that.

f1Param[1] = "f1 is Alice";
f1Param[2] = "f1 is Bob";
f1Param[p_] := "f1: undefined for param = " <> ToString[p];

f2Param[1] = "f2 is Once";
f2Param[3] = "f2 is Thrice";
f2Param[_] = "f2 defaults to something";

f3Param[p_] := "f3 directly uses param = " <> ToString[p];

f1 := f1Param[SomeNamespace`Private`param];
f2 := f2Param[SomeNamespace`Private`param];
f3 := f3Param[SomeNamespace`Private`param];

SetParam[] := SomeNamespace`Private`param = (Pause[3]; RandomChoice[{1, 2, 3}]);

Now you can

  • Test your functions without needing access to the external dependency that defines param
  • Override param as needed, but with a bit of safety
  • Implement default, variable, or shared functionality cleanly
  • Not hit a Switch every time you call a function
  • See a static list of OwnValues/DownValues instead of them being rewritten by an initialization procedure
  • Explicitly re-initialize param as needed

(These comments show a contrast with the original post, not MarcoB's solution, which shares most of these benefits.)

$\endgroup$
1
  • $\begingroup$ Thanks for your answer! This is enlightening to me! $\endgroup$
    – H. Zhou
    Aug 8 at 8:06

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.