I am debugging a program in MATLAB R2016a and would like to return from a sub-function without completing the function. For example, you can write in code:
if(conditionMet)
return;
end
If the condition is met, it will force the function to end early and continue in the caller code. While I am debugging, I would like to force the function to end early as if I had encountered a return command. When I simply type return while in debug mode, nothing appears to happens. Is there a way to force a function to end early and continue running?
According to MATLAB Central and Undocumented Matlab, there is an undocumented function feature() that could be used in your case like this:
if feature('IsDebugMode')
return;
end
I think it is not possible in general with the current release of Matlab.
If you know at beforehand at which place(s) you potentially want to return from your function while debugging, you can use the following trick.
function yourFunction ()
breakDebug = false;
...
if breakDebug
return; % location at which you may break your function during debugging
end
...
return;
end
By setting breakDebug while debugging, the program will break at your next potentially break location.
Related
I am writing a class-based test suite in MATLAB for a timeseries handling package. The first test in my suite needs to check whether a connection exists to a Haver database on a network drive. If the connection does not exist, then the first test should abort the rest of the suite using one of the fatalAssert methods.
One complicating factor, which I have excluded from the exposition below, but I will mention now is that I need to use an anonymous function to check the connection to Haver (unless someone has a better idea). My package handles data from multiple sources, Haver only being one of them.
I have a parent-class test suite that performs general tests for all of the sources. I then inherit this parent-class into specific child-class test suites and set specific parameters in their respective TestMethodSetup method. One of these parameters is an anonymous function, connfun, and a location, connloc, which I use in the parent-class to test the connection. The reason I do this is because the parent tests are executed first, so I would have to wait for all of those to end if I wanted to test the connection in the child class.
This also complicates the order of execution. If I want to assign the connfun in the child class, then I have to use either the TestMethodSetup or TestClassSetup of the child class (open to recommendations on which is best here) and put this connection test in the Test method of the parent class. I noticed the if I put checkConn in the TestMethodSetup and TestClassSetup of the parent class was running before that of the child class, I was unable to pass the anonymous function and the test would be incomplete.
Putting the previous point aside for a moment, this was my first attempt at writing the test in the parent-class (note that I used a fatalAssertEqual instead of a fatalAssertTrue because isconnection() does not return a logical):
methods (Test)
function checkConn(testCase)
connloc = 'pathToHaverDatabase';
connfun = #(x) isconnection(haver(x));
testCase.fatalAssertEqual(connfun(connloc), 1);
end
end
The above works when there is a connection, but the problem that I bumped into with this is that when I cannot access connloc, an error ocurrs during the call to haver(). So instead of returning a 1 or 0 from the isconnection() call that I can fatalAssertEqual on, all of checkConn errors out due to haver(). This then leads to the rest of the tests running (and failing, which is exactly what I want to avoid).
My next idea works for both cases, but it feels like bad code, and does not have the anonymous function specification described above.
methods (Test)
function checkConn(testCase)
connloc = 'pathToHaverDatabase';
connfun = #(x) isconnection(haver(x));
try
isconn = connfun(connloc);
catch
isconn = 0;
end
testCase.fatalAssertEqual(isconn, 1)
end
end
When I wrote this, I did not necessarily want to distinguish between not having access to the network drive, not being able to call the haver() function, and getting an isconnection equal to 0 because the last case covers all three. But I realized that if I did differentiate them, then it would be a bit more robust, but it's still missing the anonymous function taht I could pass from child to parent.
properties
connloc = 'pathToHaverDatabase';
end
methods (Test)
function checkDrive(testCase)
isfound = fillattrib(testCase.connloc);
testCase.fatalAssertTrue(isfound);
end
function checkHaver(testCase)
try
hav = haver(testCase.connloc);
ishaver = ~isempty(hav);
catch
ishaver = false;
end
testCase.fatalAssertTrue(ishaver);
end
function checkConn(testCase)
connfun = #(x) isconnection(haver(x));
testCase.fatalAssertEqual(connfun(testCase.connloc), 1);
end
end
Ideally, what I would want is a fatalAssert method (or something similar) that ends the test suite when its input is an error. Something that would perhaps be called fatalAssertNotError, but I don't think that exists. If it did, the last line of my first function would simply be testCase.fatalAssertNotError(connfun(connloc)) and I would not have to worry about all the cases.
I'm very open to dynamic rewrite of this whole test setup, so any specific comments or general advice are welcome!
First of all, I think the fatalAssert case is a strong use case to provide something like fatalAssertNotError. One reason why it is not part of the package is because many/most times people don't want to check whether something doesn't error, they just want to call the code, and if it errors, it fails for the test author automatically and it is much simpler. However, other qualification types like fatal assertions and assumptions perhaps point to the need to provide this so you can choose the outcome of the test in the presence of an error, in cases where you don't want it to fail (like with assumptions) or you want it to fail "more strongly" like with fatal assertions.
That being said, I am still not convinced that you can't achieve what you are ultimately trying to do without it. The question I have centers around why you can't use TestClassSetup. It is not clear to me exactly why you weren't able to customize in the derived test class to get the behavior you want. For example, does something like this work?
classdef BaseTest < matlab.unittest.TestCase
properties(Abstract)
connloc
connfun
end
methods(TestClassSetup)
function validateConnection(testCase)
% If this errors it behaves like an assertion (not fatal assertion)
% and fails all tests in the test class. If it doesn't error but
% doesn't return 1 then the assertion failure will occur.
testCase.assertEqual(connfun(connloc), 1,
'Could not establish a connection to the database');
end
end
end
classdef DerivedTest < BaseTest
properties
connloc = 'pathToHaverDatabase';
connfun = #(x) isconnection(haver(x));
end
methods(Test)
function testSomething(testCase)
% Have at least one test method to test it out
end
end
end
Hope that helps!
If you really want to use a function you can define a nested one like this:
methods (Test)
function checkConn(testCase)
connloc = 'pathToHaverDatabase';
function res = connfun(x)
try
res = isconnection(haver(x));
catch
res = false
end
end
testCase.fatalAssertEqual(connfun(connloc), 1);
end
end
Nested functions can be a bit confusing to me because of the way they share data with the parent function. There really is no difference between an anonymous function and a nested function.
The alternative is to put the function at the end of the file, outside the classdef block:
classdef ...
%...
methods (Test)
function checkConn(testCase)
connloc = 'pathToHaverDatabase';
function res = connfun(x)
try
res = isconnection(haver(x));
catch
res = false
end
end
testCase.fatalAssertEqual(connfun(connloc), 1);
end
end
%...
end
function res = connfun(x)
try
res = isconnection(haver(x));
catch
res = false
end
end
But I honestly don't understand why you need to have a function call within fatalAssertEqual. The code you have seems perfectly fine to me.
Background -- I was reading up on accessing shadowed functions, and started playing with builtin . I wrote a little function:
function klear(x)
% go to parent environment...
evalin('base', builtin('clear','x')) ;
end
This throws the error:
Error using clear
Too many output arguments.
I think this happens because evalin demands an output from whatever it's being fed, but clear is one of the functions which has no return value.
So two questions: am I interpreting this correctly, and if so, is there an alternative function that allows me to execute a function in the parent environment (that doesn't require an output)?
Note: I'm fully aware of the arguments against trying to access shadowed funcs (or rather, to avoid naming functions in a way that overload base funcs, etc). This is primarily a question to help me learn what can and can't be done in MATLAB.
Note 2
My original goal was to write an overload function that would require an input argument, to avoid the malware-ish behavior of clear, which defaults to deleting everything. In Q&D pseudocode,
function clear(x)
if ~exist('x','var') return
execute_in_base_env(builtin(clear(x)))
end
There's a couple issues with your clear override:
It will always clear in the base workspace regardless of where it's called from.
It doesn't support multiple inputs, which is a common use case for clear.
Instead I'd have it check for whether it was called from the base workspace, and special-case that for your check for whether it's clearing everything. If some function is calling plain clear to clear all its variables, that's bad practice, but it's still how that function's logic works, and you don't want to break that. Otherwise it could error, or worse, return incorrect results.
So, something like this:
function clear(varargin)
stk = dbstack;
if numel(stk) == 1 && (nargin == 0 || ismember('all', varargin))
fprintf('clear: balking at clearing all vars in base workspace. Nothing cleared.\n');
return;
end
% Check for quoting problems
for i = 1:numel(varargin)
if any(varargin{i} == '''')
error('You have a quote in one of your args. That''s not valid.');
end
end
% Construct a clear() call that works with evalin()
arg_strs = strcat('''', varargin, '''');
arg_strs = [{'''clear'''} arg_strs];
expr = ['builtin(' strjoin(arg_strs, ', '), ')'];
% Do it
evalin('caller', expr);
end
I hope it goes without saying that this is an atrocious hack that I wouldn't recommend in practice. :)
What happens in your code:
evalin('base', builtin('clear','x'));
is that builtin is evaluated in the current context, and because it is used as an argument to evalin, it is expected to produce an output. It is exactly the same as:
ans = builtin('clear','x');
evalin('base',ans);
The error message you see occurs in the first of those two lines of code, not in the second. It is not because of evalin, which does support calling statements that don't produce an output argument.
evalin requires a string to evaluate. You need to build this string:
str = 'builtin(''clear'',''x'')';
evalin('base',ans);
(In MATLAB, the quote character is escaped by doubling it.)
You function thus would look like this:
function clear(var)
try
evalin('base',['builtin(''clear'',''',var,''')'])
catch
% ignore error
end
end
(Inserting a string into another string this way is rather awkward, one of the many reasons I don't like eval and friends).
It might be better to use evalin('caller',...) in this case, so that when you call the new clear from within a function, it deletes something in the function's workspace, not the base one. I think 'base' should only be used from within a GUI that is expected to control variables in the user's workspace, not from a function that could be called anywhere and is expected (by its name in this case) to do something local.
There are reasons why this might be genuinely useful, but in general you should try to avoid the use of clear just as much as the use of eval and friends. clear slows down program execution. It is much easier (both on the user and on the MATLAB JIT) to assign an empty array to a variable to remove its contents from memory (as suggested by rahnema1 in a comment. Your base workspace would not be cluttered with variables if you used function more: write functions, not scripts!
I ran into the following issue in MATLAB R2013a, which for some reason I do not understand does not call the onCleanup function when in a function a timer (including a TimerFcn) is defined.
I add two minimal examples showing the problem:
first the working version where the cleanup routine is called as expected:
function mytest(time)
t = timer();
myclean = onCleanup(#() disp('function ended'));
pause(time);
end
and now the buggy version in which the cleanup is not called (neither when the function ends normally or when ctrl+c is pressed)
function mytest2(time)
t = timer();
t.TimerFcn = #(o,s)disp(' ... waiting for some time');
myclean = onCleanup(#() disp('function ends'));
pause(time);
end
I could not find any hints in documentation why the timer or more specific the definition of the TimerFcn would change the execution of the cleanup code?
Ouch - this is nasty. It's not a bug, but it's certainly not what you'd expect from the documentation, and it's not what you'd want. Fortunately it's pretty easy to work around.
Firstly, what's happening?
Well, onCleanup returns you an onCleanup object. This is an object whose sole purpose is to have a destructor method that is set to your #() disp('function ends'). When the object goes out of scope (which you would expect to be at the end of the function mytest2), it gets deleted, its destructor method executes, and your message gets displayed. That's what you expect, I think.
But when you create the anonymous function #(o,s)disp(' ... waiting for some time'), and assign it to the TimerFcn of your timer, it takes a copy of the entire current workspace of the function mytest2, including the onCleanup object. The timer is created in the base workspace (not the function workspace), and remains in existence even at the end of the function, along with the onCleanup object, which then never goes out of scope, never gets deleted, its destructor function never runs, and you don't get your message.
Note that:
If you run a = timerfindall; delete(a); in the base workspace, you will get your message, as you've explicitly deleted the timer along with the onCleanup object.
This behaviour about anonymous functions taking a copy of their entire workspace is fully documented, although you may not be aware of it, and although you clearly don't want it to work like that here. It's nasty.
Fortunately, it's easy to work around:
function mytest3(time)
t = timer();
setTimerFcn(t)
myclean = onCleanup(#() disp('function ends'));
pause(time);
end
function setTimerFcn(t)
t.TimerFcn = #(o,s)disp(' ... waiting for some time');
end
Now, when the anonymous function is created it only takes a copy of its local workspace (i.e. from the subfunction setTimerFcn), which does not include the onCleanup object. The onCleanup object goes out of scope at the point you expect it to, and everything's fine.
Hope that helps!
a possible workaround (found by a colleague of me) is to move to definition of the timer into a own function. It is not clear to us why this works but it seems that the definition of a timer in matlab changes the context of some local variables of the function which are not 'deleted' after the function ends as it would be expected from the matlab documentation (Object Life cycle of variables in Matlab)
A working example is shown below (it uses the defined timer to print simple status messages while waiting) and upon Ctrl+c or when the function ends the Timer is stopped. It furthermore makes sure that only one timer with the name 'timer-mywait' is defined.
function mytest3(time)
% register Cleanup handler
c = onCleanup(#()onCleanup_fcn);
t = mywait_timer(time);
wait(t);
% onCleanup handle function
function onCleanup_fcn
tm = timerfind('Name','timer-mywait');
if ~isempty(tm) && any(strcmpi(get(tm,'running'),'on'))
disp('Stopped running timer ''timer-mywait''!');
stop(tm);
end
end % onCleanup_fcn
end %mytest3
function t = mywait_timer(time)
N = 5;
t = timerfind('Name','timer-mywait');
if isempty(t) % avoid multiple definitions of the same timer
t = timer();
end
t.ExecutionMode = 'fixedRate';
t.TasksToExecute = N+1;
t.Period = str2num(sprintf('%.3f',time/N)); % Matlab complains about more digits!
t.Name = 'timer-mywait';
t.TimerFcn = #(o,s)mywait_timercb();
start(t),
end % mywait_timer
function mywait_timercb()
disp(' still waiting ... ');
end % mywait_timercb
I ran into the following issue in MATLAB R2013a, which for some reason I do not understand does not call the onCleanup function when in a function a timer (including a TimerFcn) is defined.
I add two minimal examples showing the problem:
first the working version where the cleanup routine is called as expected:
function mytest(time)
t = timer();
myclean = onCleanup(#() disp('function ended'));
pause(time);
end
and now the buggy version in which the cleanup is not called (neither when the function ends normally or when ctrl+c is pressed)
function mytest2(time)
t = timer();
t.TimerFcn = #(o,s)disp(' ... waiting for some time');
myclean = onCleanup(#() disp('function ends'));
pause(time);
end
I could not find any hints in documentation why the timer or more specific the definition of the TimerFcn would change the execution of the cleanup code?
Ouch - this is nasty. It's not a bug, but it's certainly not what you'd expect from the documentation, and it's not what you'd want. Fortunately it's pretty easy to work around.
Firstly, what's happening?
Well, onCleanup returns you an onCleanup object. This is an object whose sole purpose is to have a destructor method that is set to your #() disp('function ends'). When the object goes out of scope (which you would expect to be at the end of the function mytest2), it gets deleted, its destructor method executes, and your message gets displayed. That's what you expect, I think.
But when you create the anonymous function #(o,s)disp(' ... waiting for some time'), and assign it to the TimerFcn of your timer, it takes a copy of the entire current workspace of the function mytest2, including the onCleanup object. The timer is created in the base workspace (not the function workspace), and remains in existence even at the end of the function, along with the onCleanup object, which then never goes out of scope, never gets deleted, its destructor function never runs, and you don't get your message.
Note that:
If you run a = timerfindall; delete(a); in the base workspace, you will get your message, as you've explicitly deleted the timer along with the onCleanup object.
This behaviour about anonymous functions taking a copy of their entire workspace is fully documented, although you may not be aware of it, and although you clearly don't want it to work like that here. It's nasty.
Fortunately, it's easy to work around:
function mytest3(time)
t = timer();
setTimerFcn(t)
myclean = onCleanup(#() disp('function ends'));
pause(time);
end
function setTimerFcn(t)
t.TimerFcn = #(o,s)disp(' ... waiting for some time');
end
Now, when the anonymous function is created it only takes a copy of its local workspace (i.e. from the subfunction setTimerFcn), which does not include the onCleanup object. The onCleanup object goes out of scope at the point you expect it to, and everything's fine.
Hope that helps!
a possible workaround (found by a colleague of me) is to move to definition of the timer into a own function. It is not clear to us why this works but it seems that the definition of a timer in matlab changes the context of some local variables of the function which are not 'deleted' after the function ends as it would be expected from the matlab documentation (Object Life cycle of variables in Matlab)
A working example is shown below (it uses the defined timer to print simple status messages while waiting) and upon Ctrl+c or when the function ends the Timer is stopped. It furthermore makes sure that only one timer with the name 'timer-mywait' is defined.
function mytest3(time)
% register Cleanup handler
c = onCleanup(#()onCleanup_fcn);
t = mywait_timer(time);
wait(t);
% onCleanup handle function
function onCleanup_fcn
tm = timerfind('Name','timer-mywait');
if ~isempty(tm) && any(strcmpi(get(tm,'running'),'on'))
disp('Stopped running timer ''timer-mywait''!');
stop(tm);
end
end % onCleanup_fcn
end %mytest3
function t = mywait_timer(time)
N = 5;
t = timerfind('Name','timer-mywait');
if isempty(t) % avoid multiple definitions of the same timer
t = timer();
end
t.ExecutionMode = 'fixedRate';
t.TasksToExecute = N+1;
t.Period = str2num(sprintf('%.3f',time/N)); % Matlab complains about more digits!
t.Name = 'timer-mywait';
t.TimerFcn = #(o,s)mywait_timercb();
start(t),
end % mywait_timer
function mywait_timercb()
disp(' still waiting ... ');
end % mywait_timercb
I'm running a recursive function which searches a room for an object. This code is working in conjunction with another process essentially running the same code. The first thing the code does is check to see if the other one has found the object and, if so, it is supposed to break out of the function.
When I do the check to see if the other process has found the object, if it has, I use "return" to break out of that function at which time it's supposed to move onto other lines of code...However, for some reason it doesn't fully break out but instead just runs the function again and again.
Any ideas on how I can get it to break out?
I would and can provide the code but it's kind of long
EDIT
Parent script
!matlab -r "zz_Mock_ROB2_Find" & distT = 0.3;
Rob1_ObjFound = 0;
matrix = search_TEST_cam(rob, vid, 0.3, XYpos, 'north', stack, matrix, 0);
disp('I"M OUT')
Recursive code
function matrix = search_TEST_cam(rob1, vid, distT, startingPos, currentDir, stack, matrix, bT)
Rob1_ObjFound = 0;
Rob2_ObjFound = 0;
try
load('Rob2_ObjFound.mat', 'Rob2_ObjFound');
catch
end
if(Rob2_ObjFound == 1)
setDriveWheelsCreate(rob1, 0, 0);
disp('ROB_2 FOUND THE OBJECT')
pause(0.5)
BeepRoomba(rob1)
pause(0.5)
setDriveWheelsCreate(rob1, 0, 0);
return
end
Use break to break out of a for or a while loop and terminate execution, i.e., statements after that are ignored. For e.g.,
for i=1:5
if i==3
break
else
fprintf('%u,',i)
end
end
outputs 1,2, and the code terminates when i=3. If you have nested loops, break will only break out of its current loop and move on to the parent loop.
To skip only the current iteration and move on to the next, use continue. Using the same example,
for i=1:5
if i==3
continue
else
fprintf('%u,',i)
end
end
outputs 1,2,4,5,.
Using return in a function just returns control to the parent function/script that called it.
It seems like you're using the wrong one in your code. However, it's hard to tell without knowing how you're using them. Anyway, you can try one of these three and see if it makes a difference.
It's hard to say without seeing your code, but I doubt it's a problem with the RETURN statement. It's more likely a problem with how you've set up your recursion. If your recursive function has called itself a number of times, then when you finally invoke a RETURN statement it will return control from the current function on the stack to the calling function (i.e. a previous call to your recursive function). I'm guessing the calling function doesn't stop the recursion properly and ends up calling itself again, continuing the recursion.
My advice: check the exit conditions for your recursive function to make sure that, when the object is found and the most recent call returns, every previous call is properly informed that it should return as well.