Octave/matlab, multiple default arguments defined by constant - matlab

I have a problem with defining default arguments to a function in Octave/Matlab by a previously defined constant. Could someone give me a hint, why in the following code test1(1) displays 1 and 100, while test2(1) fails with error:testarg' undefined near line 1 column 36`? Thank you so much!
testarg = 100
function test1 (arg1=testarg, arg2=100)
disp(arg1)
disp(arg2)
endfunction
function test2 (arg1=testarg, arg2=testarg)
disp(arg1)
disp(arg2)
endfunction
test1(1)
test2(2)
Edit:
Please not that the order of the arguments matters:
function test3 (arg1=100, arg2=testarg)
disp(arg1)
disp(arg2)
endfunction
octave:8> test1(1)
1
100
octave:9>test3(1)
error: `testarg' undefined near line 1 column 32

I've never seen that syntax in Matlab, is it an Octave thing? In general default arguments need to be a constant rather than some other variable that may or may not be in scope or initialised at the time the function is called (feel free to educate me on languages where this isn't the case, of course).
The 'normal' way to do default arguments in regular Matlab is like this:
function test1(arg1, arg2)
if nargin < 2
arg2 = 100;
end
if nargin < 1
arg2 = testarg; % if testarg isn't in scope this still won't work
end
disp(arg1);
disp(arg2);
end

This looks like a bug to me, you should report it to the Octave developers.
In the meanwhile, here is a workaround:
testarg = 100
function test1 (arg1, arg2)
if nargin < 2, arg2 = 100; end
if nargin < 1, arg1 = testarg; end
disp(arg1)
disp(arg2)
endfunction
test1(2)
That said, it is better to be explicit here, and define them as "global variables". If the testarg is intended as a constant, better make it a function that returns said value:
testarg = #() 100;

Related

Handle undefined methods in Matlab by passing method's name and inputs to a function/method

Assume we have a Matlab class called MyClas, as below,
classdef MyClass
properties
Value
end
methods
function foo(input1, input2)
...
end
end
end
What I am looking for is having MyClass.anyThing(inputValue), where anyThing and inputValue are arbitrary strings and anyThing is not a defined method in MyClass, passes anyThing and inputValue as two strings to my foo function.
In other words, I want to be able to handle undefined methods by passing their name and inputs to a function/method as strings.
I am having a hard time to elaborate on my issue since I don't know if there is any technical term for what I am trying to pull off here. Yet, I managed to find this link from math works, which just customizes indexing operations and does not exactly address my issue.
You can emulate this by hacking in an implementation of subsref. Like this:
classdef MethodRedirector
methods
function varargout = subsref(obj, S)
if numel(S) == 2 && strcmp(S(1).type, '.') && ...
strcmp(S(2).type, '()')
% Looks like obj.method(args)
fprintf('In method invocation to: %s with args:\n', S(1).subs);
celldisp(S(2).subs);
else
[varargout{1:nargout}] = builtin('subsref', obj, S);
end
end
end
end
The restriction is that callers must use the obj.method(args...) syntax, and cannot use the (usually equivalent) method(obj, args...) syntax.
Here's how that looks in practice:
>> mr = MethodRedirector; mr.someMethod(1, '2', magic(3))
In method invocation to: someMethod with args:
ans{1} =
1
ans{2} =
2
ans{3} =
8 1 6
3 5 7
4 9 2

julia metaprogramming and nloops variable evaluation

I am a noob at metaprogramming so maybe I am not understanding this. I thought the purpose of the #nloops macro in Base.Cartesian was to make it possible to code an arbitrary number of nested for loops, in circumstances where the dimension is unknown a priori. In the documentation for the module, the following example is given:
#nloops 3 i A begin
s += #nref 3 A i
end
which evaluates to
for i_3 = 1:size(A,3)
for i_2 = 1:size(A,2)
for i_1 = 1:size(A,1)
s += A[i_1,i_2,i_3]
end
end
end
Here, the number 3 is known a priori. For my purposes, however, and for the purposes that I thought nloops was created, the number of nested levels is not known ahead of time. So I would not be able to hard code the integer 3. Even in the documentation, it is stated:
The (basic) syntax of #nloops is as follows:
The first argument must be an integer (not a variable) specifying the number of loops.
...
If I assign an integer value - say the dimension of an array that is passed to a function - to some variable, the nloops macro no longer works:
b = 3
#nloops b i A begin
s += #nref b A i
end
This returns an error:
ERROR: LoadError: MethodError: no method matching _nloops(::Symbol, ::Symbol, ::Symbol, ::Expr)
Closest candidates are:
_nloops(::Int64, ::Symbol, ::Symbol, ::Expr...) at cartesian.jl:43
...
I don't know how to have nloops evaluate the b variable as an integer rather than a symbol. I have looked at the documentation and tried various iterations of eval and other functions and macros but it is either interpreted as a symbol or an Expr. What is the correct, julian way to write this?
See supplying the number of expressions:
julia> A = rand(4, 4, 3) # 3D array (Array{Int, 3})
A generated function is kinda like a macro, in that the resulting expression is not returned, but compiled and executed on invocation/call, it also sees the type (and their type parameters of course) of the arguments, ie:
inside the generated function, A is Array{T, N}, not the value of the array.
so T is Int and N is 3!
Here inside the quoted expression, N is interpolated into the expression, with the syntax $N, which evaluates to 3:
julia> #generated function mysum(A::Array{T,N}) where {T,N}
quote
s = zero(T)
#nloops $N i A begin
s += #nref $N A i
end
s
end
end
mysum (generic function with 1 method)
julia> mysum(A)
23.2791638775186
You could construct the expression and then evaluate it, ie.:
julia> s = 0; n = 3;
julia> _3loops = quote
#nloops $n i A begin
global s += #nref $n A i
end
end
quote
#nloops 3 i A begin
global s += #nref(3, A, i)
end
end
julia> eval(_3loops)
julia> s
23.2791638775186
I have scrubbed manually the LineNumberNodes from the AST for readability (there is also MacroTools.prettify, that does it for you).
Running this example in the REPL needs to declare s as global inside the loop in Julia 1.0.

Correct use of tilde operator for input arguments

Function:
My MATLAB function has one output and several input arguments, most of which are optional, i.e.:
output=MyFunction(arg1,arg2,opt1,opt2,...,optN)
What I want to do:
I'd like to give only arg1, arg2 and the last optional input argument optN to the function. I used the tilde operator as follows:
output=MyFunction(str1,str2,~,~,...,true)
Undesired result:
That gives the following error message:
Error: Expression or statement is incorrect--possibly unbalanced (, {, or [.
The error points to the comma after the first tilde, but I don't know what to make of it to be honest.
Problem identification:
I use MATLAB 2013b, which supports the tilde operator.
According to MATLAB's documentation the above function call should work:
You can ignore any number of function inputs, in any position in the argument list. Separate consecutive tildes with a comma...
I guess there are a few workarounds, such as using '' or [] as inputs, but I'd really like to understand how to correctly use '~' because actually leaving inputs out allows me to use exist() when checking the input arguments of a function.
If you need any further info from me, please let me know.
Thank you very much!
The tilde is only for function declaration. Matlab's mlint recommends to replace unused arguments by ~. The result is a function declared like this function output = MyFunction(a, b, ~, c). This is a very bad practice.
Since you have a function where the parameters are optional, you must call the function with empty arguments output=MyFunction(str1,str2,[],[],...,true).
A better way to do it is to declare the function with the varargin argument and prepare your function for the different inputs:
function output = MyFunction(varargin)
if nargin == 1
% Do something for 1 input
elseif nargin == 2
% Do something for 3 inputs
elseif nargin == 3
% Do something for 3 inputs
else
error('incorrect number of input arguments')
end
It is even possible to declare your function as follows:
function output = MyFunction(arg1, arg2, varargin)
The declaration above will tell Matlab that you are expecting at least two parameters.
See the documentation of nargin here.
... and the documentation of varargin here
To have variable number of inputs, use varargin. Use it together with nargin.
Example:
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

Does MATLAB lets you assign default value for input arguments for a function like python does?

I am working on a project and have many functions to create and they do need lots of debugging so instead of just hitting the run button i have to go to command window and give a function call.
does MATLAB support assignment of default values to input arguments like python does?
In python
def some_fcn(arg1 = a, arg2 = b)
% THE CODE
if you now call it without passing the arguments it doesn't give errors but if you try the same in MATLAB it gives an error.
For assigning default values, one might find it easier to manage if you use exist function instead of nargin.
function f(arg1, arg2, arg3)
if ~exist('arg2', 'var')
arg2 = arg2Default;
end
The advantage is that if you change the order of arguments, you don't need to update this part of the code, but when you use nargin you have to start counting and updating numbers.
If you are writing a complex function that requires validation of inputs, default argument values, key-value pairs, passing options as structs etc., you could use the inputParser object. This solution is probably overkill for simple functions, but you might keep it in mind for your monster-function that solves equations, plots results and brings you coffee. It resembles a bit the things you can do with python's argparse module.
You configure an inputParser like so:
>> p = inputParser();
>> p.addRequired('x', #isfinite) % validation function
>> p.addOptional('y', 123) % default value
>> p.addParamValue('label', 'default') % default value
Inside a function, you would typically call it with p.parse(varargin{:}) and look for your parameters in p.Results. Some quick demonstration on the command line:
>> p.parse(44); disp(p.Results)
label: 'default'
x: 44
y: 123
>> p.parse()
Not enough input arguments.
>> p.parse(Inf)
Argument 'x' failed validation isfinite.
>> p.parse(44, 55); disp(p.Results)
label: 'default'
x: 44
y: 55
>> p.parse(13, 'label', 'hello'); disp(p.Results)
label: 'hello'
x: 13
y: 123
>> p.parse(88, 13, 'option', 12)
Argument 'option' did not match any valid parameter of the parser.
You can kind of do this with nargin
function out = some_fcn(arg1, arg2)
switch nargin
case 0
arg1 = a;
arg2 = b;
%//etc
end
but where are a and b coming from? Are they dynamically assigned? Because that effects the validity of this solution
After a few seconds of googling I found that as is often the case, Loren Shure has already solved this problem for us. In this article she outlines exactly my method above, why it is ugly and bad and how to do better.
You can use nargin in your function code to detect when no arguments are passed, and assign default values or do whatever you want in that case.
MathWorks has a new solution for this in R2019b, namely, the arguments block. There are a few rules for the arguments block, naturally, so I would encourage you to learn more by viewing the Function Argument Validation help page. Here is a quick example:
function ret = someFunction( x, y )
%SOMEFUNCTION Calculates some stuff.
arguments
x (1, :) double {mustBePositive}
y (2, 3) logical = true(2, 3)
end
% ...stuff is done, ret is defined, etc.
end
Wrapped into this is narginchk, inputParser, validateattributes, varargin, etc. It can be very convenient. Regarding default values, they are very simply defined as those arguments that equal something. In the example above, x isn't given an assignment, whereas y = true(2, 3) if no value is given when the function is called. If you wanted x to also have a default value, you could change it to, say, x (1, :) double {mustBePositive} = 0.5 * ones(1, 4).
There is a more in-depth answer at How to deal with name/value pairs of function arguments in MATLAB
that hopefully can spare you some headache in getting acquainted with the new functionality.

Anonymous function inside a script error

I created an anonymous function inside a script and I can't get MATLAB to run the fminsearch? Here's an what I have so far:
V=x(1);
f=x(2);
q=#(x) (pi.*D.*L)./(1000.*V.*f);
fminsearch(#q,x);
The variables D and L are defined, but MATLAB gives me the following error:
Error: File: Testing.m Line: 51 Column: 17
"q" was previously used as a variable, conflicting with its use here as the name of a function or command.
See "How MATLAB Recognizes Command Syntax" in the MATLAB documentation for details.
q is not mentioned before this command. What am I doing wrong?
Another thing that could solve my problem is to get my script to write a function file, but how to do that?
Remove the second #:
V=x(1);
f=x(2);
q=#(x) (pi.*D.*L)./(1000.*V.*f);
fminsearch(q,x);
q is a function handle. fminsearch expects a function handle. You can create a function handle out of a function using an # (e.g. #min), but you don't need to do that here.
You can also write the anonymous function inline with the search command:
V=x(1);
f=x(2);
fminsearch(#(x) (pi.*D.*L)./(1000.*V.*f),x);
UPDATE (credits to #wakjah)
For your code to do anything sensible, you should use the argument x of the anonymous function:
x0 = [initialV, initialF];
fminsearch(#(x) (pi.*D.*L)./(1000.*x(1).*x(2)), x0);
#function creates a function handle for an existing function.
q = #(x) whatever... creates a function handle called q.
But, you can't create a function handle for a function handle, only for a function.
See this:
>> fones = #ones
fones =
#ones
>> ffones = #fones
Error: "fones" was previously used as a
variable,
conflicting with its use here as the name
of a function or command.
See MATLAB Programming, "How MATLAB
Recognizes Function Calls That Use
Command Syntax" for details.
In Matlab, a function handle is a kind of a pointer to a function and is distinct from a function (unlike in some other languages where the a function identifier can be passed and stored as any other variable).
It's important to note that calling a function and a function handle results in the same behaviour. Except for the case where the identifier is used without any parentheses following it:
>> ones
ans =
1
>> fones
fones =
#ones
>> ones(2)
ans =
1 1
1 1
>> fones(2)
ans =
1 1
1 1