Matlab, automatically delete the index variable after the execution of a loop - matlab

On Matlab, when i am using a "for...end" loop, the indexing variable still exists in my workspace after the loop have been fully executed. I would like it to be automatically deleted, since its not relevant anymore outside of the loop and that it pollutes the workspace.
For example, in the following code, the variable "i", still exists after the execution of the loop. Since it should be a local variable, I would like it to be deleted automatically without me having to do it explicitely.
List = [1 2 3 4] ;
for i = List
fprintf('value = %i\n', i) ;
end
% "i" still exists, while its outside of its context
clear i; % I would like to avoid doing this everytime I exit a for..end
I know it is more of an aesthetic issue than a bug, but for an easier understanding of the results of my program, I would like those "temporary" variables to disappear when I exit their contexts.
So far, I only was able to reduce the number of those temporary variables by reusing them.
Edit:
It seems that there is no real solution to automatically remove those "temporary" variables.
The closest ways to avoid having those variables are:
Avoiding loops
Make the loops in functions, the variables of the functions are local and won't get in the workspace.

If you REALLY want to make sure that some of your variables have limited scope, and you want to avoid calling clear, you can use nested functions. Note that this may not help with readability, and it is more typing than calling clear. However, it does make sure that the only variables in your main function workspace are the ones that you want/need to remain.
function doSomething
List = [1 2 3 4] ;
runLoopOnList()
%# some other code here
%# nested functions
function runLoopOnList
%# i, and any other variable defined here
%# will not appear in the workspace
%# in contrast, all variables in the workspace
%# are visible and can be changed by the nested function
%# If a nested function should assign a new important
%# variable in the main workspace, have it return
%# and output.
for i = List
fprintf('value = %i\n', i) ;
end
end %# nested function
end %# main function

Look ! No loop, no iteration variable !
fprintf('value = %i\n', List)
And, while I'm here, I disagree that your i is a temporary variable; you've put it in the workspace so it is, essentially, global. Put it in another context (e.g. inside a function) if you don't want it to 'pollute' the workspace.
And yes, I know that Matlab has a concept of global variables which is slightly different from workspace variables, but it's not quite relevant here.

Related

When does the workspace change in MATLAB?

I have a couple questions regarding MATLAB workspaces:
When does MATLAB decide to change the workspace and what conditions prompt it?
Something strange is happening in the following example. I run it with a breakpoint at line 4, then step using F10 to watch the workspace variables. Clearly, I see that m is deleted within the first iteration of the inner loop, but somehow MATLAB still knows to go to the next iteration in the outer loop!
Example:
something = 2;
somethingelse = 3;
for m = 1 : something
for n = 1 : somethingelse
%do something
clearvars -except n something somethingelse % This clears m, but it still functions
end
end
The only thing I can think of is that MATLAB probably has not updated the memory locations given that the variable does not show on the list.
In MATLAB there are generally two types of workspaces: the base workspace and function workspaces. The base workspace is what you use when you enter commands at the command line, or when you run scripts (all of which share the base workspace). Conversely, each function has its own unique workspace. Unlike C or C++ (or a number of other languages) you don't have any scoping of variable within loops or conditional structures, just one unique workspace for each instance of a function.
The issue you're seeing in your example isn't really related to this, it's just an artifact of how for loops behave in MATLAB. Taken from the "Tips" section:
Avoid assigning a value to the index variable within the loop statements. The for statement overrides any changes made to index within the loop.
In other words, once an iteration of the loop completes and returns to the beginning, MATLAB ignores any changes to the loop variable and simply increments it to the next value.
If you'd like to learn more details about MATLAB workspaces and scoping, I'd check out these links:
Share Data Between Workspaces
Nested functions
Local functions
global variables
persistent variables
Function handles
Matlab changes workspace to the current scope.
You've only cleared the value of m within the scope of the second loop.
Try adding p = m+n after the clearvars command within the second loop. Since you've cleared m only within the scope of the n loop, you cannot use it. However, you did not remove m from the scope of the m loop.
Also, since the m for loop exists within the scope of your base workspace, you can clear m within the m for loop all you want, the loop will always have access to it. That's why, if you remove the clearvars line, when you return to the base workspace, you can see m and n equal to something and somethingelse respectively.
What I think you're looking for is a better explanation of Matlab's memory management, which you can find here: MATLAB's Garbage Collector?

Getting variable out in workspace from function

When I am running a function, i do not get all variables out in
work-space. When i set breakpoints than only i am able to get
variables in workspace. Therefore, how to get variables out in workspace without setting breakpoint?
While the assignin trick is handy in certain situations, one should generally not make a habit of non-explicitly 'poofing' variables across namespaces. The more obvious first approach should be to specify outputs to your function, which is basic MATLAB syntax.
If you have a small number of outputs, you can specify them individually. For example:
function [c, d] = trialcode(a, b)
% Simple summation
c = a + b;
% Simple product
d = a * b;
end
If you have many outputs, once approach is to store the desired outputs into a structure or cell array so you are outputting a single variable rather than having to specify every output. Tweaking the above example:
function [output] = trialcode(a, b)
% Simple summation
output.c = a + b;
% Simple product
output.d = a * b;
end
You can use
assignin('base','variablename',value);
to write variables from your Function-Workspace to your base-workspace.
When you use breakpoints you get to see the Workspace of the function or script that the execution stopped at. You can also choose in your Editor which Workspace(stack) you want to see in the debug mode.
If you want to write your whole Function-Workspace into your base-workspace (which in the sense of encapsulation is not recommended) you can use
vars=whos;
for k=1:length(vars)
assignin('base', vars(k).name, eval(vars(k).name));
end

Cast entire matlab workspace to some class

I'm looking for a way to cast the entire workspace in matlab to some class (say double).
For simplicity, lets just assume that only "simple" classes are present in the workspace (no cells or structs). Of course I can go line by line and change each variable, x=double(x) , but that's not practical if I have several 100's of variables. This is what I've wrote so far:
% # generate some variables of different classes
a1=int32(120);
a2=single(rand(10));
a3=double(rand(20));
a4=(rand(5)>0.5); %# logical
% # collect workspace variables using `whos`
ws=whos;
for ii=1:size(ws,1)
[ ? ] = double(eval(ws(ii).name))
end
The last line double(eval(ws{1,ii})) performs the casting, but how should I assign it's output automatically to the original variables names?
You are also welcome to suggest an alternative way to cast all variables of the workspace, if you can think of one...
Interesting question (+1). What about this?
ws = whos; %# Obtain workspace
for n = 1:size(ws,1)
eval([ws(n).name, ' = double(', ws(n).name, ');']); %# Assign to double
end
This worked for me on R2012b. The trick is to alter the variable type and assign it with one call to eval.

How do I initialize variables and have them available in the console?

For example in testinit.m I have the following
function [x, y, m] = testinit
x=4
y=3
m=2
When I run testinit in the console it correctly displays the value. However when I type x it says
error: 'x' undefined...
Just to add to the above answer, the reason you're getting this is because variables in a MatLab function are local variables, they are not passed to the workspace unless you use one of the functions in the above answer. You can read more about global and local variables here.
P.S If you wrote an m-file that is not a function, then the variables are global.
There's the assignin function (evalin is related). And also global.
The other answers are all possible solutions, but potentially more complicated than what you may be looking for. I think the first part of yuk's answer addresses the real problem you are having, but I think it deserves a more detailed explanation...
If you have a function that has output arguments, you need to actually capture those arguments in variables when you call the function. For example, if you typed this in the Command Window:
[x, y, m] = testinit;
Then you would have your three output values present for you to use. What you were probably doing was typing this:
testinit;
This would display the values (because you didn't end each line in the function with a semicolon to suppress displaying them), but it would not store them in variables in the Command Window for you to use later.
This is a result of how variables are stored in MATLAB, as described by the documentation on variable scope:
MATLAB stores variables in a part of memory called a workspace. The base workspace holds variables created during your interactive MATLAB session and also any variables created by running scripts. Variables created at the MATLAB command prompt can also be used by scripts without having to declare them as global.
Functions do not use the base workspace. Every function has its own function workspace. Each function workspace is kept separate from the base workspace and all other workspaces to protect the integrity of the data used by that function. Even subfunctions that are defined in the same file have a separate function workspace.
So, if you want to share variables between functions, the simplest way is to pass them back and forth via their input and output argument lists.
It should also be noted that the names you give variables in the output argument list of the function don't have to match the names of the variables you place those output values in. For example, given this function:
function [a, b, c] = testinit
a = 4;
b = 3;
c = 2;
You can make this call in the Command Window:
[x, y, m] = testinit;
And you will get x = 4, y = 3, and m = 2.
If you run [x, y, m] = testinit in the console you should get the variables. The output variables can have any allowed name, not necessary x, y and m.
In addition you should put ; after each variable assignment in the function to avoid their output to the console. You can control the console output while calling the function.
If you want simply initialize new variables just by typing testinit, use assignin as in #BenVoigt's answer.
assignin('base','x',4)
However, this is dangerous, since some variable may already exist in the calling environment and will be overwritten. You can avoid it adding EXIST tests (inside EVALIN):
function testinit
if ~evalin('base','exist(''x'',''var'')')
assignin('base','x',4)
end
if ~evalin('base','exist(''y'',''var'')')
assignin('base','y',3)
end
if ~evalin('base','exist(''m'',''var'')')
assignin('base','m',2)
end
You can also use 'caller' instead of 'base' if you plan to call the function from another function.
The variables are local to the function so you cannot access them from the command line. As #BenVoigt said, you can use asignin but it's very dirty, and I don't think that it's what you really want to do.
I advise you do go in debug mode
Add a break point or a keyboard to your function like that:
function [x, y, m] = testinit
x=4
y=3
m=2
keyboard
After execute your function, and the command line will remain in the environment of the function.
The usual >> kill be replaced by a K>>. At that point you can access all your local variables.
To quit the debug mode type dbquit, or press shift+F5

Matlab function handle workspace shenanigans

In short: is there an elegant way to restrict the scope of anonymous functions, or is Matlab broken in this example?
I have a function that creates a function handle to be used in a pipe network solver. It takes as input a Network state which includes information about the pipes and their connections (or edges and vertices if you must), constructs a large string which will return a large matrix when in function form and "evals" that string to create the handle.
function [Jv,...] = getPipeEquations(Network)
... %// some stuff happens here
Jv_str = ['[listConnected(~endNodes,:)',...
' .* areaPipes(~endNodes,:);\n',...
anotherLongString,']'];
Jv_str = sprintf(Jv_str); %// This makes debugging the string easier
eval(['Jv = #(v,f,rho)', Jv_str, ';']);
This function works as intended, but whenever I need to save later data structures that contain this function handle, it requires a ridiculous amount of memory (150MB) - coincidentally about as much as the entire Matlab workspace at the time of this function's creation (~150MB). The variables that this function handle requires from the getPipeEquations workspace are not particularly large, but what's even crazier is that when I examine the function handle:
>> f = functions(Network.jacobianFun)
f =
function: [1x8323 char]
type: 'anonymous'
file: '...\pkg\+adv\+pipe\getPipeEquations.m'
workspace: {2x1 cell}
...the workspace field contains everything that getPipeEquations had (which, incidentally is not the entire Matlab workspace).
If I instead move the eval statement to a sub-function in an attempt to force the scope, the handle will save much more compactly (~1MB):
function Jv = getJacobianHandle(Jv_str,listConnected,areaPipes,endNodes,D,L,g,dz)
eval(['Jv = #(v,f,rho)', Jv_str, ';']);
Is this expected behavior? Is there a more elegant way to restrict the scope of this anonymous function?
As an addendum, when I run the simulation that includes this function several times, clearing workspaces becomes painfully slow, which may or may not be related to Matlab's handling of the function and its workspace.
I can reproduce: anonymous functions for me are capturing copies of all variables in the enclosing workspace, not just those referenced in the expression of the anonymous function.
Here's a minimal repro.
function fcn = so_many_variables()
a = 1;
b = 2;
c = 3;
fcn = #(x) a+x;
a = 42;
And indeed, it captures a copy of the whole enclosing workspace.
>> f = so_many_variables;
>> f_info = functions(f);
>> f_info.workspace{1}
ans =
a: 1
>> f_info.workspace{2}
ans =
fcn: #(x)a+x
a: 1
b: 2
c: 3
This was a surprise to me at first. But it makes sense when you think about it: because of the presence of feval and eval, Matlab can't actually know at construction time what variables the anonymous function is actually going to end up referencing. So it has to capture everything in scope just in case they get referenced dynamically, like in this contrived example. This uses the value of foo but Matlab won't know that until you invoke the returned function handle.
function fcn = so_many_variables()
a = 1;
b = 2;
foo = 42;
fcn = #(x) x + eval(['f' 'oo']);
The workaround you're doing - isolating the function construction in a separate function with a minimal workspace - sounds like the right fix.
Here's a generalized way to get that restricted workspace to build your anonymous function in.
function eval_with_vars_out = eval_with_vars(eval_with_vars_expr, varargin)
% Assign variables to the local workspace so they can be captured
ewvo__reserved_names = {'varargin','eval_with_vars_out','eval_with_vars_expr','ewvo__reserved_names','ewvo_i'};
for ewvo_i = 2:nargin
if ismember(inputname(ewvo_i), ewvo__reserved_names)
error('variable name collision: %s', inputname(ewvo_i));
end
eval([ inputname(ewvo_i) ' = varargin{ewvo_i-1};']);
end
clear ewvo_i ewvo__reserved_names varargin;
% And eval the expression in that context
eval_with_vars_out = eval(eval_with_vars_expr);
The long variable names here hurt readability, but reduce the likelihood of collision with the caller's variables.
You just call eval_with_vars() instead of eval(), and pass in all the input variables as additional arguments. Then you don't have to type up a static function definition for each of your anonymous function builders. This'll work as long as you know up front what variables are actually going to be referenced, which is the same limitation as the approach with getJacobianHandle.
Jv = eval_with_vars_out(['#(v,f,rho) ' Jv_str],listConnected,areaPipes,endNodes,D,L,g,dz);
Anonymous functions capture everything within their scope and store them in the function workspace. See MATLAB documentation for anonymous functions
In particular:
"Variables specified in the body of the expression. MATLAB captures these variables and holds them constant throughout the lifetime of the function handle.
The latter variables must have a value assigned to them at the time you construct an anonymous function that uses them. Upon construction, MATLAB captures the current value for each variable specified in the body of that function. The function will continue to associate this value with the variable even if the value should change in the workspace or go out of scope."
An alternative workaround to your problem, is to use the fact that the matlab save function can be used to save only the specific variables you need. I have had issues with the save function saving way too much data (very different context from yours), but some judicial naming conventions, and use of wildcards in the variables list made all my problems go away.