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$ Commented Aug 5, 2022 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$ Commented Aug 5, 2022 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$ Commented Aug 8, 2022 at 8:06

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.