simple question on passing data between functions

点点圈 提交于 2019-11-29 04:05:40

The function Unevaluated has pretty much the same effect as (temporarily) setting the Attribute HoldFirst so you could do something like

update[a_] := Module[{}, a[[1]] = 5; a]
a = Table[0, {10}];
a = update[Unevaluated[a]]

Edit

Concerning addition 1: you could add type checking by doing something like

Clear[update];
update[a_] := Module[{}, a[[1]] = 5; a] /; Head[a] == List

Then

a = Table[0, {10}];
update[Unevaluated[a]]

works as before but

b = f[1,2,3];
update[Unevaluated[b]]

just returns the last statement in unevaluated form.

Alternatively, and if CDF allows that, you can use a pure function with a Hold*-attribute, like so:

update = Function[a, a[[1]] = 5; a, HoldFirst]

Then, you use it as usual:

In[1408]:= 
a=Table[0,{10}];
update[a];
a

Out[1410]= {5,0,0,0,0,0,0,0,0,0}

EDIT

Just for completeness, here is another way, which is less elegant, but which I found myself using from time to time, especially when you have several parameters and want to hold more than one (but such that HoldFirst or HoldRest are not good enough, such as first and third, for example): just wrap your parameter in Hold, and document it in the function's signature, like this:

updateHeld[Hold[sym_], value_] := (sym[[1]] = value; sym)

You use it as:

In[1420]:= a=Table[0,{10}];
updateHeld[Hold[a],10];
a

Out[1422]= {10,0,0,0,0,0,0,0,0,0}

EDIT 2

If your main concern is encapsulation, you can also use Module to create persistent local variable and methods to access and modify it, like so:

Module[{a},
   updateA[partIndices__, value_] := a[[partIndices]] = value;
   setA[value_] := a = value;
   getA[] := a
]

It is still (alomost) a global variable from the structural point of view, but there is no danger of name collisions with other variables, and it is easier to track where it is changed, since you only can do it by using the mutator methods above (but not directly). You use it as:

In[1444]:= 
setA[Table[0,{10}]];
updateA[1,5];
getA[]

Out[1446]= {5,0,0,0,0,0,0,0,0,0}

This is like making a simplistic JavaBean in Java - a container for mutable data (a way to encapsulate the state). You will have a slight overhead due to extra method invocations (w.r.t. Hold-attribute or Unevaluated - based methods), and in many cases you don't need it, but in some cases you may want to encapsulate the state like that - it may make your (stateful) code easier to test. Personally, I've done this a few times for UI-programming and in the code related to interfacing with a database.

In the same spirit, you can also share some variables between functions, defining those functions inside the Module scope - in this case, you may not need getter and setter methods, and such global functions with shared state are closures. You may find much more detailed discussion of this in my third post in this MathGroup thread.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!