I'm not sure is the topic title correct, but I mean such a case.
I have several functions and "changeable" global variables, e.g.:
f1[x_]:=Module[{q}, q=expr1[x, V0]; V0=expr2[V0]; q];
This means that function f1
depends on x
explicitly and on global V0
implicitly. Inside this function we compute some expression expr1
and return its result q
as a result of functioin f1
. V0
has some initial value before f1
run, and this value is changed inside f1
( as result of expr2
). This changed value of V0
is now initial value for some other function f2
, which also may change V0
. These functions f1, f2
run inside Which
construction: if an element of some list has specific property this triggers one of the f1, f2, ...
functions, after each fi
run the value of V0
is changed and this new value is initial value for next fi
.
The question is: how to correctly organize all this? Where to initiate V0
: at the very beginning of Notebook (as individual Input), or inside Which
construction (Which
is enclosed in Module
)?
Thanks.
EDIT
As I was asked in comments for details of functions and variables, there are examples.
One of the functions draws a line:
line[l_]:=Module[{q, V, W}, V=W0.straight[l] + V0; q={RGBColor[0.5,0.5,0.5], CapForm -> "Butt", Tube[{V0, V}, size]}; W=W0.mstraight; W0=W; V0=V; q];
Other functioins look similar. So, line[l]
takes length of straight as input, and also depends on "global" variables V0, W0
-- initial coordinate and direction. V0
is vector, initially defined as {0,0,0}
at the very beginning of my nb file. W0
is rotation matrix depending on 3 angles, this may change after function drawing arc, and initially W0 = IdentityMatrix[3]
. straight[l_] = {0,0,l}
and because line doesn't change direction, mstraight = IdentityMatrix[3]
, size
is global constant defining size of all the straights. Hence after this function line
run I have Tube
object (which can be drawn later together with other objects) and changed V0, W0
for input to next function as new initial coordinates and direction. Now I have these variables as globals initiated at the beginning of nb, so that every such function knows their instant changed values and may change as well.
I ask, if this approach is incorrect, please explain why and how to change it to be right.
EDIT 2
Many thanks to Anton Antonov for his versatile answer. My present code is as follows:
Module[{},v0={0,0,0}; W0=IdentityMatrix[3]; size=0.2;
(* here go other initials and constants*)
graphics=Reap[(Which[list[[#]]==somevalue1,Sow[line[...]],
list[[#]]==somevalue2,Sow[arc[...]] (* and so on*)]&)/@ Range[Length@list]][[1]];]
With Anton's approach I have to change Sow
construction to compound expression like this:
(Sow[line[...][[1]]]; {V0, W0}=line[...][[2]];)
Well, for me these additions complicate and lengthen code. I'm not programmer, just beginner in using MMA and WL, and for me my code looks more simple and transparent to control and understand, all needed changes in V0, W0
are done automatically beacause these variables are global.
Can anybody explain in simple way (understandable for novice) why globals and code like mine are not recommended in MMA? Not just for the reason that advanced users of WL are not used to do things this way, but what is really wrong, what may lead to errors. I really don't understand the advantages of approach like proposed by Anton.
The question is: how to correctly organize all this?
well, you can start by not using global variables. This is bad programming, not just in Mathematica, but in any other language. Just pass all the parameters to the function. Sorry that I can't follow the rest of your description. sometimes we use global variables here when we write code as answers, but this is just for a quick answers, and throw away code. In actual real software, global variables are not good. $\endgroup$With[{V0 = (* stuff *)}, f1[x_] := (* stuff *)]
? $\endgroup$V0
. You may think ofV0
as, say, current coordinate, or direction. E.g. eachfi
produce some geometrical object: line, or arc, andV0
is initial coordinates where to start object. Then afterfi
run we should compute new initial coordinates for next function. So,V0
is current start value forfi
, which all functions need to see and can change. $\endgroup$