# Define functions collectively depending on an input parameter

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?

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"} *)

• Thanks! Is there any advantage of using Condition over Switch (the first implementation in the question)? Aug 5 at 15:10
• @H.Zhou To me, Condition results in cleaner and more readable code that fulfills the requirements you had set out. Aug 5 at 15:13

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[SomeNamespacePrivateparam];
f2 := f2Param[SomeNamespacePrivateparam];
f3 := f3Param[SomeNamespacePrivateparam];

SetParam[] := SomeNamespacePrivateparam = (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.)

• Thanks for your answer! This is enlightening to me! Aug 8 at 8:06