Is there a way to declare a variable local in a nested function?
By declare I mean name a variable as usual but enforce that its scope starts in-place. Imagine creating a new nested function in the middle of a large program. There are natural variable names you wish to use and you would not want to worry whether you have to check existing variable names every single time you create a new variable.
To describe the desired effect, I'll use two examples. One minimal. One shows the problem a little better visually.
Short example
function fn1
var = 1
function fn2
local var = 'a';
function fn3
end
end
end
Within fn2 and fn3, var refers to the new variable with starting value 'a' while outside fn2, var with starting value 1 is still available as usual.
Long example
function fn1
var = 1;
var2 = 2;
function fn2
var2 = 'I can access var2 from fn1. Happy.'
local var = 'a'; % remove local to run this snippet
fn3;
function fn3
var2 = 'I can access var2 from fn1. Happy.'
var = 'fn2 cannot safely use variable name var because it may have been used in fn1. But var is the natural name to use in fn2. Sad.';
var = 1;
var2 = 2;
end
end
function fn4
var2 = 'I can also access var2 from fn1. Also happy.'
var = 'If only local scoping works, I would still be able to access var. Would be happy.';
end
fn4;
fn2;
var,
var2,
end
%% desired output, but not real
>> fn1;
var =
1
var2 =
2
Is there a way to accomplish the above?
Currently, I do my best ensure that name variables that are not local in nature with special non-generic names and name variables that are obviously local in nature temp# where # is an integer. (I suppose clearing variables after known last use can help sometimes. But I'd rather not have to do that. Local variables are too numerous.) That works for small programs. But with larger programs, I find it hard to avoid inadvertently re-writing a variable that has already been named at a higher scoping level. It also adds a level of complexity in the thought process, which is not exactly good for efficiency, because when creating a program, not all variables are either obviously local or obviously not local. A flexible scoping mechanism would be very helpful.
I write my programs in Sublime Text so I am not familiar with the Matlab editor. Does the editor have visual guards/warning prompts against errors arising from inflexible scoping? Warning that requires visually scanning through the whole program is barely useful but at least it would be something.
No, there is no way in MATLAB to declare a nested function variable to be local to that function if the variable also exists in the external scope (i.e., the function containing the nested function).
The behavior of Nested Functions is fully described in MATLAB documentation and what you are asking is not possible or at least not documented.
It is specifically stated that the supported behavior is
This means that both a nested function and a function that contains it can modify the same variable without passing that variable as an argument.
and no remedy to prevent this behavior is mentioned in the documentation.
Variables that are defined as input arguments are local to the function. So you can define var as an input argument of fn2*:
function fn2 (var)
...
end
However if you like to define fn2 without changing its signature you need to define an extra level of nesting:
function fn1
var = 1;
var2 = 2;
function fn2
fn2_impl([]);
function fn2_impl (var)
var2 = 'I can access var2 from fn1. Happy.'
var = 'a'; % remove local to run this snippet
fn3;
function fn3
var2 = 'I can access var2 from fn1. Happy.'
var = 'fn2 cannot safely use variable name var because it may have been used in fn1. But var is the natural name to use in fn2. Sad.';
var = 1;
var2 = 2;
end
end
end
function fn4
var2 = 'I can also access var2 from fn1. Also happy.'
var = 'If only local scoping works, I would still be able to access var. Would be happy.';
end
fn4;
fn2;
var,
var2,
end
Here fn2_impl is the actual implementation of fn2 and it inherits all variables that inherited by fn2. var is local to fn2_impl because it is an input argument.
However, I recommend local functions as suggested by #CrisLuengo. If variables need to be shared, using OO style of programming is more readable and maintainable than implicitly sharing by nested functions.
Thanks to #CrisLuengo that noted me that it is possible to skip inputs arguments when calling MATLAB functions.
Nested functions have a very specific use case. They are not intended to avoid having to pass data into a function as input and output arguments, which is to me what you are attempting. Your example can be written using local functions:
function fn1
var = 1;
var2 = 2;
[var,var2] = fn4(var,var2);
var2 = fn2(var2);
var,
var2,
end
function var2 = fn2(var2)
var2 = 'I can access var2 from fn1. Happy.'
var = 'a'; % remove local to run this snippet
[var,var3] = fn3(var,var2);
end
function [var,var2] = fn3(var,var2)
var2 = 'I can access var2 from fn1. Happy.'
var = 'fn2 cannot safely use variable name var because it may have been used in fn1. But var is the natural name to use in fn2. Sad.';
var = 1;
var2 = 2;
end
function [var,var2] = fn4(var,var2)
var2 = 'I can also access var2 from fn1. Also happy.'
var = 'If only local scoping works, I would still be able to access var. Would be happy.';
end
The advantage is that the size of fn1 is much reduced, it fits within one screen and can much more easily be read and debugged. It is obvious which functions modify which variables. And you can name variables whatever you want because no variable scope extends outside any function.
As far as I know, nested functions can only be gainfully used to capture scope in a lambda (function handle in MATLAB speak), you can write a function that creates a lambda (a handle to a nested function) that captures a local variable, and then return that lambda to your caller for use. That is a powerful feature, though useful only situationally. Outside that, I have not found a good use of nested functions. It’s just something you should try to avoid IMO.
Here's an example of the lambda with captured data (not actually tested, it's just to give an idea; also it's a rather silly application, since MATLAB has better ways of interpolating, just bear with me). Create2DInterpolator takes scattered x, y and z sample values. It uses meshgrid and griddata to generate a regular 2D grid representing those samples. It then returns a handle to a function that interpolates in that 2D grid to find the z value for a given x and y. This handle can be used outside the Create2DInterpolator function, and contains the 2D grid representation that we created. Basically, interpolator is an instance of a functor class that contains data. You could implement the same thing by writing a custom class, but that would require a lot more code, a lot more effort, and an additional M-file. More information can be had in the documentation.
interpolator = Create2DInterpolator(x,y,z);
newZ = interpolator(newX,newY);
function interpolator = Create2DInterpolator(x,y,z)
[xData,yData] = meshgrid(min(x):max(x),min(y):max(y));
zData = griddata(x,y,z,xData,yData);
interpolator = #InterolatorFunc;
function z = InterolatorFunc(x,y)
z = interp2(xData,yData,zData,x,y);
end
end
I am trying to generate a variable in Stata that is the mean of two other column variables. How can I do this? So far, I have
generate var = mean(var1 var2)
but I know that this is not correct, since mean isn't a command.
Thanks!
The problem is that mean() is not a Stata function. No Stata command has that kind of syntax.
To get the mean of two variables, you can just divide their sum by 2:
gen var = (var1 + var2)/2
If either variable is missing, the result will be missing. If you want to use the non-missing value, you could go
gen var = cond(missing(var1, var2), max(var1, var2), (var1 + var2) / 2)
or use the egen function rowmean().
How can I use a string as a variable name?
I want my variable name to be constructed during runtime, but how can I use it as a left argument and assign a value to it?
Example:
[`$"test"] : 1 / 'assign error
You could use "set" but it will create a global:
q){(`$"test") set 1;test}[]
1
q)test
1
or (as noted by user2393012 in the comments):
#[`.;`test;:;1]
If you want to avoid globals you could use some sort of namespace/dictionary/mapping:
q){d:()!();d[`$"test"]:1;d`test}[]
1
Provided .data exists, Amend At does the job:
q)#[`.data;`test;:;1] / .data not defined
'type
[0] #[`.data;`test;:;1]
^
q).data.foo: 42 / defined .data
q)#[`.data;`$"test";:;1]
`.data
q).data.test
1
Is it possible to define and use a function like this?
generate_mode_matrix_and_mode_frequency_and_Hw(generate_Hw: true);
function generate_mode_matrix_and_mode_frequency_and_Hw(generate_Hw)
if generate_Hw ## NOTICE: this argument is optional
.....
end
end
What I want is to specify the name of the argument when passing it. In ruby it's called hash.
The point of doing this is that, when using it, the coder know what the true mean without comment. This is
Compare this 2:
generate_mode_matrix_and_mode_frequency_and_Hw(generate_Hw: true)
generate_mode_matrix_and_mode_frequency_and_Hw(true)
Clearly, the first one is more clear.
Notice: generate_Hw is an optional argument. So without specifying it, the function would also work.
You can use something similar to Property\Value pairs:
function Foo(varargin)
for n=1:2:nargin
switch varargin{n}
case 'var1'
var1 = varargin{n+1};
case 'var2'
var2 = varargin{n+1};
end
end
In this example if you use Foo('var1',value) then var1 would get the desired value. If you don't specify the pair 'var1',value in the input, then var1 will not exist in Foo.
If you run this code, the variable f seems to shadow the function f. Is there anyway to reach the function f?
func f (a:Int)->Int{
return a + 43
}
var f = {(a:Int) in a + 42}
var z = f(1)
println(z)
No.
In Swift, function declarations are simply shortcuts for what you did with that closure + variable thing. That is, function names are essentially constants and should always be viewed as such (you can even pass around the function name, without brackets, as a reference).
What you're doing is you're redeclaring the name f to the variable closure. It seems Swift has a compiler issue not complaining about this. However, this problem would never occur in good code, so it's not a real problem.
It can be a bit confusing, though.