How do I exit this function? - matlab

Essentially its built like so:
.If
..other stuff
.Else
..For
...For
....If (this is where I need to be able to break out of the whole thing)
I've tried using return, and break, but they just are not working for whatever reason. I added in a ticker and it appears that the break command isn't working?
The code just continues going on and repeating the for loop even AFTER it is 'broken' in the If statement.
My function is only about 150 lines long, so I've been able to study it closely, and this seems to be where the problem is.

If you have
for (...)
for (...)
if (true)
break;
end
end
you'll only break out of the inner loop. But, of course, the outer loop will continue as normal!
Breaking out of nested-loops is one of the very few reasonable use cases for a goto. However, MATLAB does not have a goto, so you'll have to repeat yourself in some way or another:
for (...)
for (...)
if (condition)
break;
end
if (condition)
break;
end
An equally ugly yet common and less verbose way:
try
for (...)
for (...)
if (condition)
error(' ');
end
end
catch %#ok
(code you want to be executed after the nested loop)
end
or, to be pedantic,
breakout_ID = 'fcn:breakout_condition';
try
for (...)
for (...)
if (condition)
error(breakout_ID, ' ');
end
end
catch ME
% graceful breakout
if strcmp(ME.Identifier, breakout_ID)
(code you want to be executed after the nested loop)
% something else went wrong; throw that error
else
rethrow(ME);
end
end
Or you build a (nested) function containing just that nested loop, and use return to break out. But that may not always give the most "obvious" code structure, as well as cause you to have to write lots of boilerplate code (subfunction) and/or have unforeseen side effects (nested functions), so...
Personally, I favor the try/catch above.

Related

New control transfer statements (labels) for Swift 2.0

What would be the best practices for the new control transfer statements (labels) in Swift 2?
Since I hear about it I can't stop compare it with the goto command from the good and old Basic language, what never was well accepted from experient programmers at the time.
Some uses of the control flow transfer looks ok, like in example below:
outer: for i in 1...100{
for j in 1...100{
print("\(i), \(j)")
if j == 10 {
break outer
}
}
}
But what are the limitations for the control flow transfer use?
When start to be bad practice to use it?
If its use was such a bad practice why it is back?
You can prefix a loop statement, an if statement, or a switch statement with a statement label followed by a colon (:) ,break and continue statements are used to change control flow in a loop statement or a switch statement.
break statement breaks the current loop execution where as continue just breaks current iteration.
consider:
firstLoop :for j in 0...1{
secondLoop: for i in 0...10{
if (i % 2) == 0{
if (i == 4){
break firstLoop
}
print(i)
}
}
}
Output will be : 0,2
If we replace break firstloop by break secondLoop o/p Will be: 0,2,0,2
If we replace break firstloop by continue o/p Will be: 0,2,6,8,10,0,2,6,8,10
If we replace break firstloop by continue firstloop continue o/p Will be again : 0,2,0,2
If continue is followed by a statement label then it will stop the current iteration of that statement label not the loop pointed by statement label.
goto VS statement label
. goto is a kind of unconditional branching ,where you can branch anywhere in the program,The goto statement is discouraged , because it alters the sequential flow of logic .
Why statement Label is used and what is it's Limitation?
. where as continue and break can make use of statement label if and only if it is written inside the loop which has same statement label which it is using so the code will be more safer. It makes programers life easy , off course you can't directly branch out to any part of program using continue,break and statement Label it can be considered as a limitation.
I think you are asking about using labels for break and continue statements. That is a much more limited, safer use than the horrible goto statements from basic. It simply lets you tell the compiler the scope you need to break out of/continue when you have nested looping constructs.
As far as I know break and continue is the only use of labels in Swift, and for that it seems useful and appropriate.

Control flow within an eval function in Matlab

If I include a continue as a parameter of an eval() instruction, it does not work as expected. For example, when executing the following code:
listParam = {'a','b','c'};
a = 17;
b = NaN;
c = 4;
for ii=1:numel(listParam),
eval(['if isnan(',listParam{ii},'), continue; end']);
disp(['The parameter ', listParam{ii}, ' is not a NaN.']);
end
It will prompt the error:
Error: A CONTINUE may only be used within a FOR or WHILE loop.
Anybody knows why?
Note: I know that I should avoid eval() and the previous example could be refactored in a much better coding; but I found a weird behaviour and I am curious what is happening.
The expression you pass to eval must be a valid matlab expression on it's own, any surrounding code is not considered. This means each continue must be surrounded by a loop. Either put the surrounding for within your eval or put the continue outside.
As #Daniel has pointed out, eval is called by the script, while it is not directly controlled by the for loop. You can think it as: the continue in eval would move the program counter to the head of the code inside eval, but not that of the for loop; this of course would fail, as Matlab does not allow jumping between lines.
A continue can only appear directly inside a for or while loop. However, you can hack the code like this:
for ii=1:numel(listParam),
eval(['if isnan(',listParam{ii},'), x=1; else, x=0; end']);
if x
continue;
end
disp(['The parameter ', listParam{ii}, ' is not a NaN.']);
end
Strangely, x happens to appear in the script's stack. However, this is far from a good piece of code. Never use this method.
Edit: about the "control" scope of eval.
I'm not talking about the variable scope / workspace of eval. Hints can be found in several documentations like this and this. In short, eval uses the "current" workspace.
However, I found the following things interesting:
Running continue directly in eval
for ii = 1:2
eval('continue')
ii+10
end
This simply fails, as shown in the question. The error is Error: A CONTINUE may only be used within a FOR or WHILE loop. which means the continue inside eval cannot find any loop (the for loop).
Calling a separate script in a for loop
for ii = 1:2
foo
ii+10
end
while script foo.m is
ii
continue
First of all, in foo.m Mlint gives a red-line warning, which usually indicates an error that can stop the code from running, saying that CONTINUE is only valid in a FOR or WHILE loop. But pressing F5 on foo.m does not have any problem - in fact running a single continue anywhere does not crash the code.
Running the main script gives output
ii =
1
ii =
2
>>
....so foo.m catches the for loop?
eval('foo') - I really don't understand Matlab
for ii = 1:2
eval('foo')
ii+10
end
The result surprised me a bit.
ii =
1
ans =
11
ii =
2
ans =
12
>>
Thought: eval runs the code in an independent control flow, but shares its workspace with the current one. It is (something but not exactly) like an isolated world model, in which (here in Matlab) different pieces of code can interact with the same set of variables, but cannot interact with each other in the sense of control flow.
Unfortunately, I was unable to find any existing resources as reference to prove this idea.
This does not change my solution: in any case, try to avoid using eval.

open statement in a recursive subroutine

I wanted to write my results into a file which is produced in a recursive subroutine. And I also wanted to assign the data(read) in the file to an array in my main program in fortran90.
program permutations
implicit none
call generate (position_min)
open(unit=20, file="a.dat", status="old")
do i=1,720
read(20,*)(G(i,j),j=1,6)
end do
contains
recursive subroutine generate (position)
implicit none
integer, intent (in) :: position
integer :: value
if (position > position_max) then
open(unit=20, file="a.dat", status="unknown")
write (20, *) permutation
else
call generate(position+1)
end if
end subroutine generate
end program permutations
This program gives me the following runtime error.
At line 19 of file p2.f90 (unit = 20, file = 'a.dat')
Fortran runtime error: End of file
How do I fix this?
I think the answer is primarily my comment to the question. If you look at your code (neglecting the undeclared variable issue), in particular the if-statement of the recursive subroutine, you should note that you have
if (position > position_max) then
open(unit=20, file="a.dat", status="unknown")
write (20, *) permutation
else
call generate(position+1)
end if
that is, you are only writing to file if position > position_max. Satisfying this condition writes one line to a.dat and then completes all of the previous if statements. What you probably meant to have was it writing to file each time through the recursive loop; to do that, you would want something like
open(20,file="a.dat",status="unknown")
write(20,*) permutation
close(20)
if(position > position_max) then
return
else
call generate(position+1)
endif
In running this, I found I was getting 2 extra lines (due to writing at position=position_min and at position=position_max). You probably could tweak that to get exactly 720, but I think that this part is irrelevant because you can change your read loop to the following
i=1
do
read(20,*,iostat=ierr) G(i,:)
if(ierr/=0) exit
i = i+1
enddo
A normal read returns an iostat of 0 and an end-of-file returns -1, so as long as you can read you will continue the loop and break when the EOF is found.
After fixing up the undeclared variables, adding the close(20) statement, and adjusting as I commented above, I had no problems writing and reading in the recursive subroutine.

BREAK statement in PL/pgSQL

How to have the break statement in PostgreSQL? I have the structure like this:
for()
{
for()
{
if(somecondition)
break;
}
}
As per my understanding it should only break the inner for loop?
There is no BREAK in PL/pgSQL.
EXIT terminates the loop.
CONTINUE continues at the next iteration of the loop.
You can attach a <<label>> to loops and add it as parameter to each of these commands. Then you terminate / continue the labeled loop. Else, it concerns the inner loop.
RETURN exits from the function (so not applicable in a DO statement).
All of this applies to procedural elements of PL/pgSQL, not SQL.
Code example using all three:
Loop in function does not work as expected
Note, that: Yes! you need the "WHEN", even if you end up (like me ;-)) with something like
LOOP
...
IF l_my_var = 'some condition' THEN
-- this is ok, bla
IF l_debug_level >= 2 THEN
RAISE NOTICE 'debug 2: skipping a duplicate %, l_my_var;
END IF;
-- do something
CONTINUE WHEN TRUE; -- https://stackoverflow.com/questions/15173194/break-statement-in-pl-pgsql
ELSE
-- do something
END IF;
...
which looks somewhat twisted with both IF and WHEN.
Remark to the editor:
One could make the link behind "CONTINUE" more precise: https://www.postgresql.org/docs/9.6/plpgsql-control-structures.html#AEN66440

How to exit a matlab m-file (NOT the matlab itself) if the user enters bad inputs?

How to exit a matlab m-file (NOT the matlab itself) if the user enters bad inputs?
I know if a m-file goes wrong at run time we can press Ctrl-C to stop it. but I need a command to put it in my m-file to do so if something bad happens.
Please don't suggest 'exit' or 'quit' commands as they terminate the entire matlab and I don't want it.
I am not sure how you define "exit", but error seems to be the function you need.
y = input('Please input a non-negative number: ');
if(y<0)
error('input must be non-negative');
end
disp( sprintf('y=%f', y ) );
Hey I suppose you could use a try-catch combination to handle a somewhat unexpected error and do something about it.
As an example,
function [ output ] = test(input)
Bmat = [ 1 1 1 ] % Some matrix
try
input*B;
catch ME
disp(ME.message)
return; % This is the statement that exits your function
end
end
If you run
>> test([1 1 1])
It won't work since the variables 'input' and 'B' have mismatched inner dimensions, but the 'try' statement will throw an exception to 'catch', and do whatever you want from there. In this case, it will display an error message at the command line and exit the function.
The variable 'ME' here is just a MATLAB object for error handling, and ME.message stores a string containing the type of error the interpreter caught.
I just read your question again... I assume the command 'return' is probably what you are really after, you will be able use it to exit from any logic or loop statements, as well as functions.
You can read more about the 'return' command and error handling from the MATLAB documentation,
http://www.mathworks.com/access/helpdesk/help/techdoc/ref/return.html
You can just put a error command like error('bad user input') and it should stop the script.
Edit: alternatively, you could just refactor your code to not run unless you set the input flag to be true. Something like
inp = input('>', s)
if validateInput(inp)
%do you stuff here or call your main function
else
fprintf('Invalid input')
end