I am using Matlab R2013a and I am trying to use the 'who' function within a function to retrieve a list of variables that begin with a name.
Let's say I have a list of variable in my workspace as follows:
a = 1
a_2 = 2
a_3 = 3
when I run this:
who('a*');
it works fine.
But when I run the same thing inside a function like this:
function someFunction()
who('a*');
end
or
function someFunction()
disp(who('a*'));
end
It doesn't. No error, just no output.
If I had saved those variables in a Matlab file called
myVariables.mat
and run this within the same function like so:
function someFunction()
who('a*','myVariables');
end
It still doesn't work.
I can understand why the first might not work because of scope, but specifying the file to run the 'who' function on should work... what am I missing?
Any help would be appreciated.
Regards
Diaa
As mentioned by #Daniel, the workspace of a function is separate from the base workspace. There are two ways you could use who inside a m-file to inspect the base workspace:
Use a script instead of a function (i.e. omit the function- line; launch the script by its file name as you do with a function): A script shares the base workspace, and thus, who will be able to see all your variables.
Use evalin: evalin('base','who')
You are trying to access variables within a function. Only the input arguments and global variables are visible within a function. You have to do something like:
function someFunction(a1,a2)
who('a*');
end
If you are really trying to use dynamic variable names, I would strongly recommend to change your design.
Related
I am looking for a workaround for the following problem:
Create a script foo.m containing fun = #(x)(x*x)
Run foo. This creates the variable fun.
Delete foo.m
Try running fun(2).
In recent versions of MATLAB (I am using R2019b) this results in an error:
Previously accessible file "foo.m" is now inaccessible.
Somehow, the anonymous function is tied to the file in which it was defined.
Is it possible to somehow "detach" it so that it would continue working even after the file was deleted?
For those curious why I need this, it is for fixing MATLink, the Mathematica/MATLAB interface, for recent versions of MATLAB.
You can use func2str and str2func to construct a new function handle that will work:
more_fun = str2func(func2str(fun));
more_fun(2)
Note that after this, fun can still not be found, but you can also assign to fun directly to make it accessible again.
Edit: just found a (documented) limitation: if the anonymous function uses outside variables, this method will not work, because
Function handles created using str2func do not have access to variables outside of their local workspace or to nested functions. If your function handle contains these variables or functions, MATLABĀ® throws an error when you invoke the handle.
I would like to have a list of constants readily available to use in any script or function I write. For example, I have been defining constants like hbar (Planck's constant) at the start of any script that will be using it.
Instead of that, should I:
make a list of constants in a script and load that script every time
I want to use it,
or save constants in a workspace and load that,
or is it possible for me to have global variables that will be there even when I close and reopen Octave,
or something else?
If you use GNU Octave I would suggest using the miscellaneous package and the function physical_constant which already has 335 constants. In your case:
[val, uncertainty, unit] = physical_constant ("Planck constant over 2 pi")
val = 1.0546e-34
uncertainty = 4.7000e-42
unit = J s
If you want don't want this, then use functions, not global vars.
As you indicated, there are a few ways to solve this problem. To address your third option, which seems to be closest to the spirit of what you want, you've got at least two ways of handling this.
1.) If the variables need to be mutable. Create a function or script that initializes the variables to what you want them to be. I'm going to reference the MATLAB documentation but it should basically be the same.
function initglobals()
global the_answer
the_answer = 42;
end
Then any time you want to use these globals in a script, you first indicate to Octave that you'll be using the variable as a global:
...
global the_answer
disp(the_answer) %prints 42
...
For this to be more useful, I'd recommend generating a startup script and putting in your .octaverc docs. This startup script can call this function to initialize your globals.
2.) Your other choice, if the globals ought to be immutable (for example, a physics constant) is to define a function that returns the value you want.
function [out] = the_answer()
out = 42;
end
Then you can simply just use the_answer to access your constant.
In both cases you'll want to add these functions to your path. Create your collections of functions and put them somewhere, then add that location to your path. docs
I have a function in a separate file
function [ ] = loadModel( model , version )
cd(model.path);
loadPath = strcat(model.name(1,:) , model.versions(version,:), '_results' ) ;
load(loadPath,'-mat');
end
which using model structure and version number as inputs changes directory to the one of the model and loads its results. When I call the function from a m-file there is no error but its seems like none of the lines of the function have been executed e.g. a variable loadPath doesn't even exist. When I put a break point before load(), I see loadPath generated correctly and if I type the last line manually it works fine. Any clues why is this happening?
P.S. I am used to C++, Java and I find the matlab language absolute nighmare
This is because you're only loading the file within the scope of the loadModel function. In MATLAB, variables declared within a function (this includes through file loading) are only defined within that function (barring global variables, assignin, etc). You need to return the results of the file load in order to use the loaded data. For instance:
function data = loadModel( model , version )
cd(model.path);
loadPath = strcat(model.name(1,:) , model.versions(version,:), '_results' ) ;
data = load(loadPath,'-mat');
end
This will load the file into a struct, which is returned to the calling scope. You can then access the loaded data from this struct.
You need to understand the concept of workspace: the function workspace is different from the base workspace (the one you can access from the command line). Your function executes normally and the variable loadPath is created, but in the function workspace, not the base workspace. As your function doesn't return anything you don't have access to it. In debug mode, you get access to the function workspace, so you can see the variable. You need the function to return the variable of interest if you want to access it from the base workspace. I suggest you have a look at the documentation, it's very thorough.
I'm learning MatLab & hit a roadblock.
I have an interface.fig file with interface.m which is acting as my 'main' GUI window. From there another file; bright.m is called.
The file bright needs to update global variables in the main file as well as call functions, I have worked out the global variables out but cannot call functions.
Tried everything, looked at doing things like:
reDisplay();
evalin('base','reDisplay()');
interface.reDisplay();
interface>reDisplay();
But had no luck.
Only the first function in an M file is callable from outside of that file. If you want your functions to be globally accessible then you need to save them in independent files.
If you need state to be globally accessible between these functions pass them as arguments or consider using an Object Oriented approach to solving your problem.
If a function in Matlab is defined inside an m-file with file name different than function name - then there is no way of calling this function from outside its m-file.
In order for your reDisplay function to be visible to bright.m, you should have this function in its own m-file called reDisplay.m
Is it possible to retrieve a local variable from a programme-function i've run in matlab? i.e. i want to retrieve a variable from the code, which is not appeared in the outputs.
Thanks in advance
The following describes code to add to the function itself to make the variable available outside the local scope. When you can't change the function, from the outside there is nothing to be done about changing the scope of course (which is intended, correct behaviour!!).
Dirty ways:
global variables
global t
t=2.468;
For scalars, strings, simple values: assign to variables in base workspace using evalin:
t=2.468;
evalin('base', ['var_in_base=' num2str(t) ';']);
Any other variable, use assignin:
A=magic(20);
assignin('base','A',A);
Proper way:
Inspect them during debugging
If you really want them outside the local scope, add them as output variable!!
Look at Declare function. You can access local variables if you return them as return values. If you do not, you can't access them from outside.
So in
function [mean,stdev] = stat(x)
n = length(x);
mean = sum(x)/n;
stdev = sqrt(sum((x-mean).^2/n));
You have access to mean and stdev but there is no way to access n.
I don't know matlab at all, but from programmer's logic
that seems improper and impossible without hacking the code.
That being said, through Google I saw this:
When you call a script from a function, the script uses the function workspace.
Like local functions, nested functions have their own workspaces. However, these workspaces are unique in two significant ways:
Nested functions can access and modify variables in the workspaces of the functions that contain them.
All of the variables in nested functions or the functions that contain them must be explicitly defined. That is, you cannot call a function or script that assigns values to variables unless those variables already exist in the function workspace.
Base and Function Workspace
Not sure if this helps you at all, but it may clarify some points