octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Nested functions, documented?


From: David Shih
Subject: Re: Nested functions, documented?
Date: Mon, 21 Nov 2011 17:34:34 -0500
User-agent: Opera Mail/11.51 (Linux)


| function y = primary_function(x, a, b)
|   y = sub_function( @(x) sub_function(x, a, b) );
| end

Sorry. That's a mistake.
It should just instead be:

| function y = primary_function(x, a, b)
|   % use anonymous function to create a closure
|   func = @(x) sub_function(x, a, b);
|
| % now, when func is called at some future point, only x need to be passed explicit; a and b are passed by the anonymous function
|   z = func(x);
|
| % this is particularly useful when using functions such as arrayfun to avoid for-loops:
|   % Z = arrayfun(func, X);
| % suppose X is an array, and Z is the output array, and sub_function(..) normally only handle x as a scalar value
| end
|
| function z = sub_function(x, a, b)
| % sub_function accesses parameter variables a and b, which are in scope
|   z = x + a + b;
| end


I forgot about the ability to write to variables in nested functions. I typically avoid doing this, as it creates a mess. I only really use nested functions for use with arrayfun or cellfun to avoid for-loops and to organize a procedure inside a function for re-use.


My particular need for nested function, originally written for Matlab and now translated to use subfunction + closure


function y = evaluate(X, kmax)
%EVALUATE(X, K)
%Return score array y based on data matrix X, where y_i corresponds to the score of X evaluated based on parameters 1:kmax

%% for-loop version

y = zeros([kmax 1]);
for i in 1:kmax
  Y(i) = evaluate_k(X, i);
end


%% arrayfun version: No for-loop!

% wrap subfunction s.t. X does not need to be explicitly passed in function call
func = @(k) evaluate_k(X, k);
y = arrayfun(func, k);

end


function y = evaluate_k(X, k)
  % complex evaluation code
  % y = some final score
end


For the ability to write to shared variables, I would use classes, and declare the shared variables as class members.


David



On Mon, 21 Nov 2011 16:25:28 -0500, John W. Eaton <address@hidden> wrote:


On 19-Nov-2011, David Shih wrote:

| I ran into the same problem where my Matlab code using nested function is
| affected by the variable scope issue.
|
| I have not seen a workaround on the list, so I am providing one here:
|
| You can use anonymous functions with subfunctions to achieve the same effect
| as nested functions.
| It may even be desired that the programmer explicitly pass the variables
| into a subfunction using an anonymous function, so that nested function
| variable scopes do not become a mess.
|
|
| An example:
|
| *Nested version*:
|
| function y = primary_function(x, a, b)
|
|   function z = nested_function(x)
| % nested_function accesses variables a and b from the parent function
|     z = x + a + b;
|   end
|
|   y = nested_function(x);
|
| end

| function y = primary_function(x, a, b)
|   y = sub_function( @(x) sub_function(x, a, b) );
| end
|
| function z = sub_function(x, a, b)
| % sub_function accesses parameter variables a and b, which are in scope
|   z = x + a + b;
| end

Given that you are writing this complex expression:

   y = sub_function( @(x) sub_function(x, a, b) );

which already involves A and B as arguments to the subfunction, why
not simplify things and write

   y = subfunction (x, a, b);

instead?

Also, the version with the function handle trick is not equivalent to
nested functions because nested functions can change values in the
calling scope.  For example, with Matlab, I think the following
program will print x = 3 and a = 4 and y will be undefined outside the
scope foo the nested function:

  function foo ()
    x = 1;
    a = 2;
    function bar (y)
      y = -1;
      x = 3;
      a = 4;
    end
    bar (x);
    x
    a
    y
  end

I don't think you can get those semantics from some trick with
function handles and subfunctions because the function handle gets a
copy of the variables from the calling scope, and the subfunction
can't directly modify values in the caller.

And, I would add, those semantics are precisely what makes nested
functions such an awful software maintenance nightmare.  At the very
least, a way to declare variables as local to a nested function should
have been added to the language at the same time.

jwe


reply via email to

[Prev in Thread] Current Thread [Next in Thread]