Is there a way for a matlab function to access all variables in a script - matlab

I have a script with lots of variables (10-30), and in a for loop I do some processing using basically every variable. I have a helper script so that the interior of the loop looks clean.
main script
a=2;b=5;c=8;d=10;%and many many more
for i=1:1000
helper;
end
I want to turn helper into a function, primarily because this would allow me to have the helper script (now a function) at the bottom of the main file. But I definitely do not want to individually pass every variable and every variable that I have yet to need in this project.
What I really need is a goto, but matlab doesnt have it.

There are many solutions to this. In rinkert's comment you've gotten the only one that is good coding practice: put the variables in a struct, then pass the struct into your function. I highly recommend that you do that. Using nested functions is not a terrible solution either, though it could be a lot more difficult to manage (variable visibility rules are funny in nested functions, I find it confusing at times).
Here I'm going to give you the worst possible solution: evalin. You should not do this, I post this here for educational purposes only.
evalin allows a function to retrieve a variable in the caller's workspace:
a=2;b=5;c=8;d=10;%and many many more
for i=1:1000
helper;
end
function helper
% NEVER DO THIS IN PRACTICE
a = evalin('caller','a');
b = evalin('caller','b');
c = evalin('caller','c');
d = evalin('caller','d');
% do computations....
assignin('caller','result',result);
end
Note that a function result = helper(a,b,c,d) is much more efficient and much easier to maintain because it's clear what is going on. evalin makes for surprising results, and assignin even more so. Do not use this.
There are a few legitimate uses of these functions. For example, I've written a GUI that allows a MATLAB user easier access to a set of functions, but is meant to work in conjunction with the interactive MATLAB command prompt. The GUI would fetch variables from the 'base' workspace, evaluate function calls in the 'base' workspace, and write new variables to the 'base' workspace. Running a function within the GUI is just like running it at the command prompt. There is no other way of accomplishing this other than using evalin and assignin.

although it's not good coding conduct, you could use global variables :
for example :
global a;
a= 5;
function out =test()
global a;
out=2*a;
end

Related

Define a variable and use it in all sub-function on Matlab

Is there any way to define a variable in main function and use it in all sub-function.
I've tried to declare variables as global but it seems I should repeat it in all function again. I'm wonder what's the benefit of global variable at all!
use variable as global:
main program
global x
syms x
subfunc1
subfunc2
...
and
subfunc1
global x
and
subfunc2
global x
(maybe this format remind us to have global variable in function but it was better to cause error if we use same name of variable in function same as Matlab keywords)
I don't want to import the variable as all function argument and don't want to declare that variable in all function again and again.
any help would be appreciated.
If you really want to have access to the same variable, then there are only two ways I know of in Matlab:
nested functions(described by answer from #justthom8) and global variables. Other methods of getting data into functions exist, such as getappdata, guidata and (my personal favorite:) passing function arguments. However, these approaches make copies of variables.
Perhaps you should ask yourself why you want to avoid making copies of variables. If you are worried about performance, you should know that Matlab efficiently use variables as reference to data only, so you can safely send a variable in to a function (thereby copying the variable) without copying the actual data. its first after you modify the data inside of the function that the data is actually copied. All this is totally invisible to us, except as a possible drop in performance during alot of copying. This is called copy-on-write.
Global variables can be used to optimize Matlabs performance, by coding them in such a way as to avoid copying data, but that really requires knowing what you are doing, and it opens up for a whole lot of pitfalls, especially if your projects grow in size.
One thing you can do is define the other functions as subfunctions of the main function. Something like below
Both of the functions subFunc1 and subFunc2 should have access to data you define above it in mainFunc
function mainFunc()
variable1 = 'stuff';
variable2 = 5;
function subFunc1()
%do stuff
end
function subFunc2()
%do more stuff
end
end
Edit 1
Of course you can define global data in the mainFunc that gets used in the subfunctions, but I wouldn't recommend doing that since it can get changed in unexpected ways that you don't intend for to happen.

Octave: How should I go about having global constants handy for any program?

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

Good way to pass many variables to function?

When one has a function, which needs many specific variables when called, what is a good way, to pass them?
Should one always pass all variable explicitly? How about storing them in structs (or objects)? But somehow I think, this makes things a bit obscure, as these structs/objects have to be well defined to make sure, they have all the fields, when handed in to the function in question.
Also probably local variables are accessed most quickly, whereas adressing struct fields might be slow in a loop...
Or is it a good thing to run an external script where everything is defined global (but even in this case on has to make everything available to the function using the global keyword)
A good way to pass many variables to a function, is to use varargin. Use it together with nargin.
function varlist2(X,Y,varargin)
fprintf('Total number of inputs = %d\n',nargin);
nVarargs = length(varargin);
fprintf('Inputs in varargin(%d):\n',nVarargs)
for k = 1:nVarargs
fprintf(' %d\n', varargin{k})
end
Varargin can also be used for optional variables.. So it gives a lot of options...

Find indirect calls to specific built-in MATLAB function

What do I want?
I am looking for a way to detect all points in my code where a specific function is called.
Why do I want it?
Some examples:
Some output comes out sorted or randomized, and I want to know where this happens
I am considering to change/overload a function and want to know in which part of my code this could have impact
What have I tried?
I tried placing a breakpoint in the file that was called. This only works for non builtin functions which are called from short running code that always executes everything.
I tried 'find files', this way I can easily find direct calls to sort but it is not so easy to find a call to sort invoked by unique for example.
I have tried depfun, it tells me:
whether something will be called
from where non-builtin functions will be called
I thought of overloading the builtin function, but feels like a last resort for me as I am afraid to make a mess. | Edit: Also it probably won't help due to function precedence.
The question
What is the best way to track all potential (in)direct function calls from a specific function to a specific (built-in)function.
I don't exactly understand your use case, but I guess most of the information you want can be obtained using dbstack, which gives you the call-stack of all the parent functions calling a certain function. I think the easiest way is to overload built-in functions something like this (I tried to overload min):
function varargout = min(varargin)
% print info before function call
disp('Wrapped function called with inputs:')
disp(varargin)
[stack,I] = dbstack();
disp('Call stack:')
for i=1:length(stack)
fprintf('level %i: called from line %i in file %s\n', ...
i, stack(i).line, stack(i).file);
end
% call original function
[varargout{1:nargout}] = builtin('min', varargin{:});
% print info after function call
disp('Result of wrapped function:')
disp(varargout)
I tried to test this, but I could not make it work unfortunately, matlab keeps on using the original function, even after playing a lot with addpath. Not sure what I did wrong there, but I hope this gets you started ...
Built-in functions take precedence over functions in local folder or in path. There are two ways you can overload a built-in for direct calls from your own code. By putting your function in a private folder under the same directory where your other MATLAB functions are. This is easier if you are not already using private folder. You can rename your private folder once you are done investigating.
Another way is to use packages and importing them. You put all your override functions in a folder (e.g. +do_not_use). Then in the function where you suspect built-in calls are made add the line "import do_not_use.*;". This will make calls go to the functions in +do_not_use directory first. Once you are done checking you can use "clear import" to clear all imports. This is not easy to use if you have too many functions and do not know in which function you need to add import.
In addition to this, for each of the function you need to follow Bas Swinckels answer for the function body.
Function precedence order.
Those two methods does not work for indirect calls which are not from your own code. For indirect calls I can only think of one way where you create your own class based on built-in type. For example, if you work only on double precision types, you need to create your own class which inherits from double and override the methods you want to detect. Then pass this class as input to your code. Your code should work fine (assuming you are not using class(x) to decide code paths) since the new class should behave like a double data type. This option will not work if your output data is not created from your input data. See subclassing built-in types.
Did you try depfun?
The doc shows results similar to the ones you request.
doc depfun:
...
[list, builtins, classes, prob_files, prob_sym, eval_strings, called_from, java_classes] = depfun('fun') creates additional cell arrays or structure arrays containing information about any problems with the depfun search and about where the functions in list are invoked. The additional outputs are ...
Looks to me you could just filter the results for your function.
Though need to warn you - usually it takes forever to analyze code.

How to retrieve local variables?

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