Apple Blocks added to C++?
Reimer Behrends
behrends at gmail.com
Thu Sep 3 05:40:26 PDT 2009
Walter Bright wrote:
> The reason for nested functions are:
>
> 1. factoring out repeated code within the function into a nested function
>
> 2. locality - a nested function is adjacent to where it is used, rather
> than somewhere else
>
> 3. isolation - by scope rules, it is easy to see the nested function and
> all calls to it
You don't actually need nested functions for that. Consider, for
example, Tarjan's algorithm [1] to find strongly connected components in
a directed graph. It's normally a prime example of where you would use
nested functions: It's got some scaffolding to set up temporary state,
then repeatedly calls a recursive helper algorithm that operates on the
temporary state. Without going into the details of the algorithm, you
can basically write it as follows (using Scala as an example, though of
course it would also work in D, OCaml, etc.):
class DirectedGraph[V] {
...
def stronglyConnectedComponents: Set[Set[V]] = {
def recursiveHelper(vertex: V) = { ... }
...
}
...
}
However, you could also factor out the algorithm into a class of it's own:
class StronglyConnectedComponents[V](val graph: DirectedGraph[V]) {
def findAll: Set[Set[V]] = { ... }
private def recursiveHelper(vertex: V) = { ... }
}
This satisfies all your three criteria above. The potentially repeated
code is factored out into its own function, the helper function is next
to where it is used, and you can see who call it since it is private.
However, unlike a nested function, you have additional benefits: You can
reuse the helper function, for starters. And since the algorithm isn't
an integral part of the DirectedGraph class anymore, you can furthermore
improve the refactoring, since the algorithm doesn't need the full
graph, but only a set of vertices and a successor function:
class StronglyConnectedComponents[V](val vertices: Set[V],
val successors: V => Set[V]) {
def findAll: Set[Set[V]] = { ... }
private def recursiveHelper(vertex: V) = { ... }
}
Now we can use the algorithm not only for directed graphs, but also for
other, similar data structures that do not need to be a subtype of
DirectedGraph.
>> However, nested functions are hidden inside their parent, which means
>> that they are not reusable;
>
> That's actually a feature, see (3).
As I showed above, you can have both locality and reusability. These are
not mutually exclusive properties.
>> on top of that, object-oriented languages already have means to share
>> state between multiple methods (which is sometimes imperfect, but so
>> are nested functions).
>
> Nested classes (Java) and functors (C++) are pretty ugly next to nested
> functions.
I am not even talking about nested classes, just classes (see above).
Classes are the standard vehicle in most object-oriented languages for
having multiple functions operating on shared state.
Mind you, I'm not saying that this is the only approach to deal with
such issues (and it has imperfections of its own). Just that it is an
alternative, equally valid way of doing things.
Reimer Behrends
[1]
http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
More information about the Digitalmars-d
mailing list