Nested Methods? Why are they useful? [closed]
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
开发者_StackOverflow中文版 Improve this questionSo I'm just learning some new stuff in C# & Python. Turns out both lanuages support nested methods (C# sort of does).
Python:
def MyMethod():
print 'Hello from a method.'
def MyInnerMethod():
print 'Hello from a nested method.'
MyInnerMethod()
C# (using new features in .NET 3.5):*
static void Main()
{
Console.WriteLine("Hello from main.");
Func<int, int> NestedMethod =
(x) =>
{
Console.WriteLine("In nested method. Value of x is {0}.", x);
return x;
};
int result = NestedMethod(3);
}
So why are nested methods so important? What makes them useful?
**The C# code has not been tested. Feel free to edit if it doesn't compile.*
First, realize I cannot give you a complete list. If you were to ask "why are screwdrivers useful?", I would would talk about screws and paint can lids but would miss their value in termite inspection. When you ask, "Why are nested functions useful?", I can tell you about scoping, closures, and entry points.
First, nesting can be an alternative to classes. I recently wrote some rendering code that took a file name for specialized mark-up code and returned a bitmap. This naturally lead to functions named grab_markup_from_filename() and render_text_onto_image() and others. The cleanest organization was one entry point named generate_png_from_markup_filename(). The entry point did its job, using nested functions to accomplish its task. There was no need for a class, because there was no object with state. My alternative was to create a module with private methods hiding my helpers, but it would be messier.
def generate_png_from_markup_filename(filename):
def grab_markup_from_filename():
...
... # code that calls grab_markup_from_filename() to make the image
return image
Second, I use nesting for closures. The most common example is for creating decorators. The trick is that I return a reference to an inner function, so that inner function and the outer parameter value are not garbage collected.
def verify_admin(function_to_call):
def call_on_verify_admin(*args, **kwargs):
if is_admin(global.session.user):
return function_to_call(*args, **kwargs)
else:
throw Exception("Not Admin")
return call_on_verify_admin # the return value of verify_admin()
use it this way:
def update_price(item, price):
database.lookup(item).set_field('price', price)
update_price = verify_admin(update_price)
or, more concisely:
@verify_admin
def update_price(item, price):
database.lookup(item).set_field('price', price)
And yes, it should be hard to trace. Remember that "def" is just another statement.
So, here are two places nested classes are helpful. There are more. It is a tool.
Nested methods are useful because there are many cases where you want to pass behaviour around, rather than just data. In many instances, it is clearer and easier to follow, in addition to being easier and faster to write, to just define that behaviour in the body of your method, where you are going to use it.
In .NET, LINQ is a great example of this. Suppose you wanted to create a list where each value was double its value in the original list:
list.Select(i => i*2)
where i => i*2
is equivalent to:
Func<int,int> double = delegate(int x) { return x*2; }
This is much simpler and clearer than creating a separate function.
Further, the function you declare may not have meaning elsewhere (ie, outside the scope of your method). In C#, you can even reference to variables declared inside your method body -- which you cannot do with a non-nested function.
Of course, you can also abuse nested functions...
Nested methods also allow you to control scope of the caller as well as allowing you to access internally created members without them being exposed to other functions in a similar scope (i.e. inside of a class)
Nested methods increase locality of your code which is a good thing as you don't have to pollute classes with small private methods used only in one place.
Try this Pythonish pseudocode example for a glimpse at one use-case for this technique:
def MyMethod(base):
base = expensivePreparation(base)
def MyInnerMethod(some_modifier):
doSomethingCoolWith(base, some_modifier)
return MyInnerMethod
process = MyMethod(some_obj)
process(arg1)
process(arg2)
Many useful answers here already, but here goes.
- inner classes: not! nice try, but too much make-work. Nested functions / procs are much quicker and to the point. King Java's [1] classes with one method [2] really suck, and nested functions (or procedures) circumvent such syntactic nonsense.
- functional decomposition: break a long routine into smaller ones, which are hidden from other places where they aren't used. Pascal supported this eons ago, and I'm pretty sure it wasn't a new invention even then (early 70s).
- closures: mentioned elsewhere, but useful. use local variables in the enclosing function to initialize the generated function, and return a customized function (or otherwise use the generated code)
1: http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html "King Java"
2: http://en.wikipedia.org/wiki/Function_object#In_Java "Function object / functor"
Along the above mentioned points, these can be treated as Higher order functions, functions that themselves take or return functions.
Check out this example:
static void Main(string[] args)
{
Func<int, int> NestedMethod = delegate(int x)
{ Console.WriteLine("In nested method. Value of x is {0}.", x);
return x;
};
HigerOrderTest(NestedMethod)();
}
private static Action HigerOrderTest(Func<int, int> highFunction)
{
var sam = highFunction(3);
Action DoIt =() =>
{
Console.WriteLine("Output is {0}.", sam);
};
return DoIt;
}
You are perhaps already aware of the usefulness of passing functions to other functions, for example, providing a sort()
routine with a comparison function, and the obvious examples of map()
and filter()
and so on. Likewise, it is often useful to receive functions as a result from another function. The most common usage is for closures, but currying is also common.
A central benefit of a closure is being able to create a new function at runtime that contains all the temporal information required for its execution at that point in time. In language implementations that don't support closures, such state management is usually done, arguably less elegantly, via classes: object instance variables are set, and then later read when needed. Closures provide a means to bundle the state with the action.
So as a basic point of understanding, it may help to think of nested functions as a way to write on-the-spot functions to perform very specific actions where the details of those actions will be known at runtime, but you only want to execute that action at some later time.
There are other things that can be done with nested functions, but you have to start somewhere.
精彩评论