Checking existence of a input argument to a Matlab function - matlab

I'm trying to check the input of a Matlab function to see whether the user has forgotten about it or not (which is easy to do in this case).
If the user has not supplied number_obs then I want to pause the program and wait for the user to input this information.
Some other StackOverflow posts seem to suggest using ~exist however this doesn't seem to work. Can anybody suggest what I'm doing wrong here?
function output=test(number_obs)
if ~exist('number_obs'),
number_obs=input('How many observations do you have in your experiments?')
end
The Python equivalent would be something like:
def test(number_obs):
if nummber_obs != None:
output=raw_input('How many observations do you have in your experiments? :')
return output

You can do this with nargin
function output=test(number_obs)
if nargin<1
number_obs=input('How many observations do you have in your experiments?')
end

(Edited to correct the truth) It may not matter here, but to be on the safe side, you should always specify the type of object you're checking. In your case, its a 'var', so
if ~exist('number_obs','var'),
Thanks to dasdingonesin for pointing this out.

Related

Is it possible to use fsolve if an existing script return a class structure?

I have a script Function.m such that for example, when I write TEST=Function(1,2), I have TEST.x1=4 and TEST.x2=[5,6,7]. I want to use fsolve to help me find input. To be precise, I want to define a function, say a=#(y)Function(1,y)-4 so that when I use [z,vector]=fsolve(#(y)a(y),5), matlab can help me to obtain z=2 and vector=[5,6,7].
I would like to solve it by defining the same structure New_Function.m as Function.m such that it returns x1 values, i.e., TEST=New_Function(1,2) gives TEST=4 only. Then I write new_a=#(y)New_Function(1,y)-4 and solve z=fsolve(#(y)new_a(y),5) and define new_vector=Function(1,z) so that I can access new_vector.x2.
I want to know if it is possible to do my task without defining a new script or amending the content in the existing script. How to write code?
Since Matlab does not allow further referencing the result of a function call, you may need to help yourself with getfield. In your example (provided I got it right), it would be something like New_Func = #(y) getfield(Function(1,y),'x1'). This would take one scalar and return one scalar, i.e., New_Func(y) gives the field value of the struct returned by Function(1,y) associated to the field x1.

equivalent of `evalin` that doesn't require an output argument (internally)

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!

How MATLAB's "if" function handles multiple inputs

I ran a quick test to see how if deals with multiple input values. It appears that the default behavior is to apply and to the collection of values, but I couldn't find any documentation. Can anyone confirm or provide a counterexample?
>> if([1,1,1]) disp(sprintf('hi'));end;
hi
>> if([1]) disp(sprintf('hi'));end;
hi
>> if([1,1,0]) disp(sprintf('hi'));end;
EDIT: to clarify, I don't intend to try to use this "feature," but wanted to be sure I knew how erroneous input would be handled. Suppose, for example, your code read
if(my_function) and the (badly written) my_function usually returns a single value but occasionally returns multiple values. Good practice, of course , would parse the returned values appropriately and feed a single value to if.
I don't find any practical reason to create an if statement which depends on anything but a scalar.
Regarding what's done in MATLAB practically?
You may assume MATLAB applies the function all on the input of the if statement.
This will hold as intuition given the array is non empty.
For example, if we have array - array4Example which is not empty, the statement if on the array - if(array4Example) is equivalent of the statement if on the scalar - if(all(array4Example(:))).
This matches the documentation if the if function.

Why is depfun(fun) returning 'too many output arguments' (MATLAB)

depfun's documentation gives the following:
[list,builtins,classes] = depfun(fun) returns the MATLAB classes that
fun requires.
Excellent, this is exactly what I want. However, when I call that on my function it tells me there are too many output arguments. So, I tried
list = depfun(Dynamo)
and to my surprise the same error occurred. How can this be? depfun(Dynamo) must return at least one argument, no?
What I'm trying to do is to create a dependency graph in the way as suggested by Andrew Janke in Automatically generating a diagram of function calls in MATLAB
The following works and gives me a nice report, but I don't want the graph to contain all the hidden functions which is why I'm opting for depfun.
profile on
Dynamo;
profile off
profview
Any insight is much appreciated
You need to pass the function argument as a string
>> [list,builtins,classes] = depfun( 'Dynamo' )

How can I make the value of an expression equal to a second return value of another expression

Is there an idiomatic way in Matlab to bind the value of an expression to the nth return value of another expression?
For example, say I want an array of indices corresponding to the maximum value of a number of vectors stored in a cell array. I can do that by
function I = max_index(varargin)
[~,I]=max(varargin{:});
cellfun(#max_index, my_data);
But this requires one to define a function (max_index) specific for each case one wants to select a particular return value in an expression. I can of course define a generic function that does what I want:
function y = nth_return(n,fun,varargin)
[vals{1:n}] = fun(varargin{:});
y = vals{n};
And call it like:
cellfun(#(x) nth_return(2,#max,x), my_data)
Adding such functions, however, makes code snippets less portable and harder to understand. Is there an idiomatic to achieve the same result without having to rely on the custom nth_return function?
This is as far as I know not possible in another way as with the solutions you mention. So just use the syntax:
[~,I]=max(var);
Or indeed create an extra function. But I would also suggest against this. Just write the extra line of code, in case you want to use the output in another function. I found two earlier questions on stackoverflow, which adress the same topic, and seem to confirm that this is not possible.
Skipping outputs with anonymous function in MATLAB
How to elegantly ignore some return values of a MATLAB function?
The reason why the ~ operator was added to MATLAB some versions ago was to prevent you from saving variables you do not need. If there would be a syntax like the one you are searching for, this would not have been necessary.