Why does Octave not encapsule variables inside of nested functions? - function

When writing nested functions in Octave, the variables do not seem to be encapsuled:
function r = asd()
fn1();
endfunction
function res1 = fn1()
res1 = 0;
function res2 = fn2()
res2 = 0;
for i = 10:20
res2 = res2 + i;
endfor
endfunction
for i = 1:10
printf("i before calling fn2(): %d\n", i);
res1 = res1 + fn2();
printf("i after calling fn2(): %d\n", i);
endfor
endfunction
This seems very odd to me because it screams for bugs, right? Is there a specific reason the variables are not encapsuled here?

Nested functions exist explicitly to share variables with the enclosing function. This is their purpose. If you don’t want a private function to share variables with the calling function, declare it after the calling function in the same M-file. This makes it a “local function”, a function only visible from within this file.
In general nested functions are weird and should only be used in specific circumstances. One place they are useful is to encapsulate variables in a more complex lambda than can be accomplished with an anonymous function:
% Returns a function that depends on x
function f = createLambda(x)
y = atan(x); % some calculation
function res = nested(val)
res = y * val; % …but this would be several lines or a loop or whatever
end
f = #nested
end
Nested functions exist in Octave because they were introduced in MATLAB. You should read the excellent MATLAB documentation to learn more about them.

Related

How to define a function with a parameter in it in Octave?

I am trying to define a function with a predefined variable, and Octave says that the variable was not defined. I am trying to run the following code in Octave,
q = 5;
function w = tointegrate(x)
w = 2 * q * sin(x);
endfunction
[ans, ier, nfun, err] = quad("tointegrate", -10*q, 10*q);
ans
Octave gives the error
error: 'q' undefined near line 3 column 10
error: quad: evaluation of user-supplied function failed
How to fix this error?
You are expecting 'commandline functions' in octave to have lexical scope, but this is simply not the case.
If all of this was inside a function, and you defined a nested function, it would work as you expect. But 'commandline functions' like this are treated as if they are in their own file, and have no knowledge of the workspace in which they've been defined.
In this particular case, since your function is effectively a one-liner, you can get the effect you want by making it a function handle instead, which 'does' capture the local workspace. I.e. this will work
q = 5;
tointegrate = #(x) 2 * q * sin(x);
[ans, ier, nfun, err] = quad("tointegrate",-10 *q ,10*q);
Note, however, that 'q' will have the value it had at the time it was captured. I.e. if you update q dynamically, its value will not be updated in the function handle.
Otherwise, for more complex functions, the solution is really to pass it as a parameter (or to access it as a global etc).
You can solve this by having q be a parameter to the function, then creating an anonymous function to call quad, like so:
function w = tointegrate(x, q)
w = 2 * q * sin(x);
endfunction
q = 5;
[ans, ier, nfun, err] = quad(#(x)tointegrate(x,q), -10*q, 10*q);
ans

Scilab not returning variables in variable window

I have created a function that returns the magnitude of a vector.the output is 360x3 dimension matrix. the input is 360x2.
Everything works fine outside the function. how do i get it to work ?
clc
P_dot_ij_om_13= rand(360,2); // 360x2 values of omega in vectors i and j
//P_dot_ij_om_13(:,3)=0;
function [A]=mag_x(A)
//b="P_dot_ijOmag_"+ string(k);
//execstr(b+'=[]'); // declare indexed matrix P_dot_ijOmag_k
//disp(b)
for i=1:1:360
//funcprot(0);
A(i,3)=(A(i,2)^2+A(i,1)^2)^0.5; //calculates magnitude of i and j and adds 3rd column
disp(A(i,3),"vector magnitude")
end
funcprot(1);
return [A] // should return P_dot_ijOmag_k in the variable browser [360x3 dim]
endfunction
mag_x(P_dot_ij_om_13);
//i=1;
//P_dot_ij_om_13(i,3)= (P_dot_ij_om_13(i,2)^2+P_dot_ij_om_13(i,1)^2)^0.5;// example
You never assigned mag_x(P_dot_ij_om_13) to any variable, so the output of this function disappears into nowhere. The variable A is local to this function, it does not exist outside of it.
To have the result of calculation available, assign it to some variable:
res = mag_x(P_dot_ij_om_13)
or A = mag_x(P_dot_ij_om_13) if you want to use the same name outside of the function as was used inside of it.
By the way, the Scilab documentation discourages the use of return, as it leads to confusion. The Scilab / Matlab function syntax is different from the languages in which return specifies the output of a function:
function y = sq(x)
y = x^2
endfunction
disp(sq(3)) // displays 9
No need for return here.

Is it possible to know the name of the variable that provides the value in a function call in Octave?

Say that myFunction has been invoked from somewhere like this
...
myFunction (b);
...
Now, in the definition of myFunction, can I obtain the name of the variable in the call?
function myFunction (a)
...
inputVble = whoscalling; % this will result in "b"
...
May be it can be done if b is a global variable?
Note: this is not like in a couple other questions, where you want to know the name of the input argument, i.e. a.
function ret = doit (a, b)
inputname (1)
inputname (2)
ret = a + b;
endfunction
x = 4;
y = 5;
doit (x, y)
returns
ans = x
ans = y
ans = 9
But I want to mention that in my opinion, making a function somewhat dependent on the function names is bad style and shouldn't be done even if it's possible.
EDIT: I think the main reasonable use for inputname is inside a display routine for #classes. For example http://hg.savannah.gnu.org/hgweb/octave/file/51a1d1164449/examples/code/%40polynomial/display.m
function display (p)
...
fprintf ("%s =", inputname (1));
Or inside celldisp:
octave:2> a = {"huhu", pi}
a =
{
[1,1] = huhu
[1,2] = 3.1416
}
octave:3> celldisp (a)
a{1} =
huhu
a{2} =
3.1416

Passing additional arguments through function handle in Matlab

I have a function to optimize, say Function, in Matlab. This function depends on variables (say x) over which I want to optimize and one parameter (say, Q) which does not need to be optimized.Hence, the function Function(x,Q). In other words, I have an array of values for Q and want to find optimal x values for each Q. However, I cannot find a way how to pass those Q values when using function handle #Function in optimization function.
So, my question is how to pass those Q values when using function handle in optimization functions, for example fmincon(#Function,x0,A,b)?
Try using anonymous function:
x = cell( 1, numel(Q) );
for qi = 1:numel( Q )
x{qi} = fmincon( #(x) Function(x, Q(qi)), A, b );
end
As described in MATLAB documentation, there are actually 3 solutions for this problem:
Anonymous Functions
which is described in the Shai's answer of this post.
Nested Functions:
in this approach the outer function accepts all arguments, and the inner function only accepts parameters that optimization takes place on them.
this is an example taken from MATLAB documentation:
function [x,fval] = runnested(a,b,c,x0)
[x,fval] = fminunc(#nestedfun,x0);
% Nested function that computes the objective function
function y = nestedfun(x)
y = (a - b*x(1)^2 + x(1)^4/3)*x(1)^2 + x(1)x(2) +...
(-c + cx(2)^2)*x(2)^2;
end
end
Global Variables
in this approach you should define the parameters that are needed in objective function as global in workspace, and use them in objective function with declaring them as global.
here is an example again from MATLAB documentation:
Defining objective function:
function y = globalfun(x)
global a b c
y = (a - b*x(1)^2 + x(1)^4/3)*x(1)^2 + x(1)x(2) + ...
(-c + cx(2)^2)*x(2)^2;
end
Optimization:
global a b c;
a = 4; b = 2.1; c = 4; % Assign parameter values
x0 = [0.5,0.5];
[x,fval] = fminunc(#globalfun,x0)
You may be able to do the following:
x = fmincon(fun,x0,A,b,Aeq,beq,lb,ub,nonlcon,options,Q)
which will pass Q along to fun(x,Q)!

MATLAB function syntax within script?

Having some trouble declaring functions within my script:
%Read the raw audio data
refData = wavread('file1.wav');
userData = wavread('file2.wav');
% I want to continue writing my "main" function here, and call the below functions
%%%%%%%%%%%%%
% Functions %
%%%%%%%%%%%%%
%Vector x
function preEmphasis(x)
alpha = 0.95;
len = length(x);
for i=1:len
x_i = x(i);
x_iMinus1 = x(i-1);
x(i) = x_i - alpha*x_iMinus1;
end
end
%Vector x
function normalization(x)
maxVal = max(abs(x));
x = x / maxVal;
end
%Vector x; numFrames, frameSize: integers; stepSize: percentage (float, 0.2 -> 0.5 for example)
function Ymatrix = createYmatrix(x, numFrames, frameSize, stepSize)
Ymatrix = zeros(numFrames, frameSize);
for i=1:numFrames
for j=1:frameSize
Ymatrix(i,j) = x(stepSize*i + j);
end
end
end
The words "function" and "end" are highlighted in red as "parse errors". How can I fix this? Thanks.
You can't declare functions within your main script. You have to create an external m-file and implement your function inside it, like it says in the official documentation:
Any function that is not anonymous must be defined within a file.
(just to be clear, a script does not accept input arguments or return output arguments).
However, you can have local functions declared inside a function m-file.
Read more about function declarations in the official documentation.
EDIT: You can Refer to #natan's answer if you're looking for a way to avoid function m-files altogether. He implemented your functions as anonymous functions, which can be declared inside the script file. Good luck!
In Addition to what Eitan mentioned, here is how to implement an anonymous functions in your case, note that code vectorization is a must. For example, in your case instead of normalization you can write:
normalization = #(x) x./max(abs(x));
and then use it as if it was a function, y=normalization(x)
For preEmphasis:
preEmphasis= #(x) [x(1) x(2:end)-0.95*x(1:end-1)];
Your current code has a bug for the case i=1 so I interpret that as for=2:len instead;
The solution for Ymatrix is a bit ugly (haven't invested to much time vectorizing it nicely), but it should work:
Ymatrix = #(x, numFrames, frameSize, stepSize) ...
ones(1,numFrames)'*x(1+stepSize:stepSize+frameSize)+...
meshgrid(0:stepSize:stepSize*numFrames-1,ones(1,frameSize))';
Just turn your script into a function; then you can use local and nested functions. Use return values or assignin if you need to get values back in to the base or caller's workspace.