In Octave I can suppress or hide the output of an instruction adding a semicolon to the end of a line:
octave:1> exp([0 1])
ans = [ 1.0000 2.7183 ]
octave:2> exp([0 1]);
octave:3>
Now, how can I suppress the output if the function displays text (e.g. using disp() or print()) before returning its value? In other words, I want to be able to do this:
disp("Starting...");
% hide text the may get displayed after this point
% ...
% show all text again after this point
disp("Done!");
You can modify the PAGER variable (which is now a function) to redirect standard output. On Unix systems, you can redirect it to /dev/null. On Windows, I tried simply redirecting to a Python program that does nothing, and it works decently. (Basically, any program that ignores the input will do)
PAGER('/dev/null');
page_screen_output(1);
page_output_immediately(1);
You can just change it back after you're done. And maybe encapsulate this whole procedure in a function.
oldpager = PAGER('/dev/null');
oldpso = page_screen_output(1);
oldpoi = page_output_immediately(1);
% Call function here
PAGER(oldpager);
page_screen_output(oldpso);
page_output_immediately(oldpoi);
You can also simply run your scripts non-interactively, and redirect the output normally.
octave script.m > /dev/null
A quick hack of your problem and maybe not even worth mentioning is overloading the disp function like so:
function disp(x)
end
Then the original disp function is not called but yours instead in which no output is generated.
I also tried to somehow redirect stdout of octave, but unsuccessful. I hope that this dirty solution maybe will suffice in your situation^^
It's a very old question, but still, I've encountered the same problem and here is the trick that can help. One can use evalc to wrap a problematic function call. E.g. you have a code:
[a, b] = verbose_func(x,y);
Now you can do it:
evalc('[a, b] = verbose_func(x,y)');
and make it silent.
Funny, but it even works with other eval inside. I mean we can have:
code_str = '[a, b] = verbose_func(x,y)';
eval(code_str);
which is verbose. Now:
code_str = '[a, b] = verbose_func(x,y)';
evalc('eval(code_str)');
and this is not.
Related
If I write this:
clc
clear
close all
format long
fprintf( 1, 'Starting...\n' )
function results = do_thing()
results = 1;
end
results = do_thing()
And run it with Octave, it works correctly:
Starting...
results = 1
But if I try to run it with Matlab 2017b, it throws this error:
Error: File: testfile.m Line: 13 Column: 1
Function definitions in a script must appear at the end of the file.
Move all statements after the "do_thing" function definition to before the first local function
definition.
Then, if I fix the error as follows:
clc
clear
close all
format long
fprintf( 1, 'Starting...\n' )
results = do_thing()
function results = do_thing()
results = 1;
end
It works correctly on Matlab:
Starting...
results =
1
But now, it stopped working with Octave:
Starting...
error: 'do_thing' undefined near line 8 column 11
error: called from
testfile at line 8 column 9
This problem was explained on this question: Run octave script file containing a function definition
How to fix it without having to create a separate and exclusive file for the function do_thing()?
Is this issue fixed on some newer version of Matlab as 2019a?
The answer is in the comments, but for the sake of clarity:
% in file `do_thing.m`
function results = do_thing()
results = 1;
end
% in your script file
clc; clear; close all; format long;
fprintf( 1, 'Starting...\n' );
results = do_thing();
Accompanying explanatory rant:
The canonical and safest way to define functions is to define them in their own file, and make this file accessible in octave / matlab's path.
Octave has supported 'dynamic' function definitions (i.e. in the context of a script or the command-line) since practically forever. However, for the purposes of compatibility, since matlab did not support this, most people did not use it, and quite sensibly relied on the canonical way instead.
Matlab has recently finally introduced dynamic function definitions too, but has opted to implement them explicitly in a way that breaks compatibility with octave, as you describe above. (rant: this may be a coincidence and an earnest design decision, but I do note that it also happens to go against prior matlab conventions regarding nested functions, which were allowed to be defined anywhere within their enclosing scope).
In a sense, nothing has changed. Matlab was incompatible with advanced octave functionality, and now that it has introduced its own implementation of this functionality, it is still incompatible. This is a blessing in disguise. Why? Because, if you want intercompatible code, you should rely on the canonical form and good programming practices instead of littering your scripts with dynamic functions, which is what you should be doing anyway.
Octave's implementation of local functions in scripts is different from Matlab's. Octave requires that local functions in scripts be defined before their use. But Matlab requires that local functions in scripts all be defined at the end of the file.
So you can use local functions in scripts on both applications, but you can't write a script that will work on both. So just use functions if you want code that will work on both Matlab and Octave.
Examples:
Functions at end
disp('Hello world')
foo(42);
function foo(x)
disp(x);
end
In Matlab R2019a:
>> myscript
Hello world
42
In Octave 5.1.0:
octave:1> myscript
Hello world
error: 'foo' undefined near line 2 column 1
error: called from
myscript at line 2 column 1
Functions before use
disp('Hello world')
function foo(x)
disp(x);
end
foo(42);
In Matlab R2019a:
>> myscript
Error: File: myscript.m Line: 7 Column: 1
Function definitions in a script must appear at the end of the file.
Move all statements after the "foo" function definition to before the first local function definition.
In Octave 5.1.0:
octave:2> myscript
Hello world
42
How it works
Note that technically the functions here in Octave are not "local functions", but "command-line functions". Instead of defining a function that is local to the script, they define global functions that come into existence when the function statement is evaluated.
The following code works on both Matlab and Octave:
if exist('do_nothing') == 0
disp('function not yet defined, run script again')
else
do_nothing
end
%====
function results = do_nothing()
results = 1;
end
When run on octave, the first attempt exits with the message, but subsequent attempts succeed. On Matlab, it works the first time. While this works on both platforms, it is less than ideal, since it requires that much of the script code be placed inside an "if" statement block.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I already showed that the performance of str2func is better, but I got a lot of comments stating that there are more fundamental reasons to not use eval. Which fundamental reasons do apply to eval and do not apply to str2func in the following situation:
f='a^x+exp(b)+sin(c*x)+d'
eval:
y = eval(f)
or (suggested by rahnema1)
fHandle = eval(['#(x, a, b, c, d) ' f]);
y = fHandle(x, a, b, c, d);
str2func:
fHandle = str2func(['#(x, a, b, c, d) ' f]);
y = fHandle(x, a, b, c, d);
Why is the first option worse than the second one except for performance reasons?
Remarks
Note that I'm aware that it is good practice to avoid both methods if possible.
Note that I assign the output of eval to a variable, which avoids a lot of tricky code from being executed.
Stop trying to downplay the security risk that is eval. Running arbitrary code can be harmful if you don't fully control the input. If you fully control the input, there is almost always a better way that doesn't involve dynamic code generation.
You insist on a specific example:
>> ls TMPFILE
Error using ls (line 35)
ls: cannot access 'TMPFILE': No such file or directory
>> y = eval('system(''touch TMPFILE'')');
>> y
y =
0
>> ls TMPFILE
TMPFILE
touch is a very friendly unix command; it creates an empty file. Imagine rm -rf ~ in the same context.
Let's try it with str2func:
>> y = str2func('system(''touch TMPFILE2'')');
Warning: The input to STR2FUNC "system('touch TMPFILE2')" is not a valid function name. This will generate an error in a future release.
>> ls TMPFILE2
Error using ls (line 35)
ls: cannot access 'TMPFILE2': No such file or directory
>> y
y =
function_handle with value:
#system('touch TMPFILE2')
>> y()
Undefined function or variable 'system('touch TMPFILE2')'.
Side note: while the risk of eval is real and not just due to superstition, not using eval doesn't necessarily mean you're safe. My favourite example, the sneaky devil of str2num:
>> x = str2num('[system(''touch TMPFILE3'')]')
x =
0
>> ls TMPFILE3
TMPFILE3
So even if you're not explicitly using eval, it might happen that a convenience function you're using instead does. You should always make sure that this doesn't happen: use the safe str2double instead of str2num, and use str2func instead of eval (since we saw above that str2func won't execute arbitrary code).
First, performance (especially x100 slower) should be enough reason to not use something.
However, you are missing the point. You are now asking "why not use eval in the specific example of evaluating a function in a string?". Well, the answer of that is because you have a function called str2func to specifically do this job faster and more safely. The reason you should not use eval is because in the cases you want to use eval, the logic of your code is flawed.
The only reason to eval is to evaluate an arbitrary input that is not just a function on a string (why would you do that, you already showed that there is an specific function for it). If you know what you are evaluating, then you don't need eval, you can write code for what you expect. Thus, eval is only of use when you accept generic inputs. But generic inputs include rm -rf to delete your whole OS. Or in a less catastrophic case, the code may rewrite over a variable that is important for the rest of the algorithm. It is obvious why you dont want to let your code run arbitrary inputs.
What about dynamic variables? A terrible idea that can be generated using eval. And you may accidentally make this by accepting arbitrary inputs.
But there are more things. eval does make your code unreadable. You have no idea what the code does, until runtime.
I have seen code that does this within its core functions
model.solve_algorithm=eval(['default(',[ class(input3) ],')']);
result=eval(model.solve_algorithm);
What does the code do? What are the options? There is no way to know, unless you run it, and see where it goes. This makes the code obfuscated and hard to read, and certainly hard to maintain. Being explicit in code is something that does benefit a lot in maintainability of code.
TLDR: In any case that you may want to use eval, one of the two is happening:
There is a better, more specific function for what you want to do
You really should not be doing what you are trying to do, code/logic needs restructuring.
I'll put aside the arguments against both methods for a moment, although they are all very valid and a conscientious reader should try to understand them.
I can see two clear differences. For these examples we have to assume you've constructed the input string to the functions in your script, using some variable data, and assume it could be anything (by mistake or otherwise). So we prepare and account for the worst case.
str2func includes some extra checks to make sure what you've passed is a valid function, which might avoid unwanted behaviour. Let's not take the stance of "yeah but you could do it this way to avoid that" and look at an example...
% Not assigning an output variable
% STR2FUNC: You've harmlessly assigned ans to some junk function
str2func('delete test.txt')
% EVAL: You've just deleted your super important document
eval('delete test.txt')
% Assigning an output variable
% STR2FUNC: You get a clear warning that this is not a valid function
f = str2func('delete test.txt')
% EVAL: You can a non-descript error "Unexpected MATLAB expression"
f = eval('delete test.txt')
Another difference is the subject of about half the str2func documentation. It concerns variable scopes, and is found under the heading "Examine Differences Between str2func and eval".
[Intro to the function]
If you use a character vector representation of an anonymous function, the resulting function handle does not have access to private or local functions.
[Examine Differences Between str2func and eval]
When str2func is used with a character vector representing an anonymous function, it does not have access to the local function [...]. The eval function does have access to the local function.
So to conclude, you might have use cases where each function is preferable depending on your desired error handling and variable scoping should never use eval or str2func wherever possible, as stated in the other answers.
TL;DR - eval has access to locally defined functions while str2func does not. The "right" function to use among these two depends on the structure of your code.
Without getting into the whole "why eval is bad" discussion, I shall try to focus on the relevant piece of MATLAB documentation that discusses it in the context of your question:
Consider a file with two functions:
function out = q46213509
f='a^x+exp(b)+sin(c*x)+d';
fHandle = {eval(['#(x, a, b, c, d) ' f]), str2func(['#(x, a, b, c, d) ' f])};
out = [fHandle{1}(1,2,3,4,5) fHandle{2}(1,2,3,4,5)];
end
function e = exp(x)
e = x.^0./factorial(0) - x.^1./factorial(1) + x.^2./factorial(2); % Error is deliberate
end
When you run the above, it results in :
ans =
8.7432 26.3287
If you're working with classes and you define your own operators this might get out of hand... Let's say somebody decided to add a file to your MATLAB path, and conveniently give it the name of some function you use, or that of an overloadable operator (i.e. mpower.m):
function out = mpower(varargin)
% This function disregards all inputs and prints info about the calling workspace.
disp(struct2cell(evalin('caller','whos')));
end
While in some cases, MATLAB protects from redefinition of builtin functions, I bet the scenario above might confuse str2func quite a lot...
I have a collection of smaller scripts foo1, foo2, etc. and a script master.m that runs them all, like this:
% master.m
run foo1
run foo2
Let's say foo1 calls for input somewhere by saying a = input('Gimme a number\n');.
I thought that if I put the value(s) I wanted on new lines after the run command that they would be entered as input, but they don't. I've also tried enclosing them as a string, i.e. '5'. That doesn't work either.
Is their another function I should use? I looked at the help file for input, but there's no output function. Presumably there's something like write or writetostdio somewhere.
How do I give user input to a script that is being called by another script without touching the keyboard? Can I put the values I want to input in the master.m file?
EDIT:
Because there's some confusion, I'll try to clear it up.
The scripts foo1 and foo2 will NOT be passing values back and forth. Every script will be run independently. Instead, I'm trying to test a program for a range of user behaviours (which are responses to prompts via input in foo1). These are normally typed on the keyboard, but I want my master.m file to tell foo1 what the user inputs are.
Sorry if this is confusing, but hopefully that clears it up.
Modifying existing code to accommodate both manual input and testing inputs is trivial:
function foo1(niterations)
if nargin == 0
niterations = round(input('How many iterations? '));
end
for ii = 1:numel(niterations)
% Run the thing
fprintf('Running some random program with %d iterations! Yay!\n', niterations(ii));
end
end
Using this approach we can do:
>> foo1
How many iterations? 2
Running some random program with 2 iterations! Yay!
or
>> foo1(2)
Running some random program with 2 iterations! Yay!
or
>> foo1([1, 3, 5, 7, 9])
Running some random program with 1 iterations! Yay!
Running some random program with 3 iterations! Yay!
Running some random program with 5 iterations! Yay!
Running some random program with 7 iterations! Yay!
Running some random program with 9 iterations! Yay!
This is far more logical than trying to pipe things from text files, use evalin to poof things into workspaces, or whatever automagical approach is required to accommodate using scripts in this fashion.
Ok, this is a bit ugly... but might be a work-around if for some reason foo1.m etc. have to remain as scripts.
The idea is to replace each instance of input with a newly defined function myInput which checks if a variable PROMPT_VALUE has been set in the base work-space; and returns that if so, and otherwise passes through to the built-in input. For example:
% myInput.m
function [ valueOut ] = myInput( promptString )
W = evalin('caller','whos'); %or 'base'
doesPVexist = ismember('PROMPT_VALUE',[W(:).name]);
if doesPVexist
valueOut = evalin('caller', 'PROMPT_VALUE');
else
valueOut = input(promptString);
end
end
Assuming we have the following sub-scripts:
% foo1.m
a = myInput('Number to double: ');
disp(2*a);
% foo2.m
b = myInput('Number to halve: ');
disp(b/2);
We can test the approach as follows:
% master.m
clearvars;
PROMPT_VALUE=5;
run foo1.m;
PROMPT_VALUE=3;
run foo2.m
If you run this as-is it will take the PROMPT_VALUE as inputs to each of the subscripts (returning 10, and 1.5). If those lines are commented out it will look for input from the user.
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.
Say that, on a MATLAB interactive session, I call a function from a third party library output = long_execution(input). This function prints information via disp statements to the command window. I would like to capture the output of such disp statements on a text string that I can manipulate in MATLAB.
Is there a (hopefully easy) way of redirecting the output of disp to a text string? If so, how would you do it? (maybe via the overlading of disp?)
You can use evalc function to capture disp outputs. For example,
[T, output] = evalc('long_execution(input)');
Anything that would normally go to command window is captured into the output T.
If everything is going into stdout, you can use the diary function to capture that and write it to file, then after execution you can use any number of matlab file reading utilities to parse through it. You might also find the function tempdir and tempname useful in this context.