Re: Recursive blocks
Re: Recursive blocks
- Subject: Re: Recursive blocks
- From: Chris Suter <email@hidden>
- Date: Sun, 30 Jan 2011 05:26:35 +1100
Hi Glen,
On Fri, Jan 28, 2011 at 7:03 PM, Glen Low <email@hidden> wrote:
[snip]
> The recursive block allows me to hide the recursion within a method, also
to
> avoid having to return more than 1 type (BOOL + GKGraph*) from the
recursion
> i.e. avoiding the ugly GKGraph** smallestCluster parameter.
>
> On the other hand, the block formulation is not quite in sequence with how
> the code actually flows either -- which is one of the advantages of block
> programming IMHO. At least the block code is not too far visually from the
> invoking code.
The use of a block here looks pretty ugly in my opinion. I don't see
returning more than one type as being a big deal. Also, in the function
case, I don't believe there's a need for the GKGraph * parameter; you can
use self.
Having said all that, does your algorithm need to be recursive? Wouldn't
this do the same job more efficiently without recursion:
- (GKGraph *)enclosingClusterForNodes:(NSSet *)someNodes
{
if (![someNodes isSubsetOfSet:nodes])
return nil;
GKGraph *cluster = self;
LOOP:
for (GKGraph *subcluster in cluster.subgraphs) {
if (subcluster.isCluster && [someNodes isSubsetOfSet:subcluster.nodes])
{
cluster = subcluster;
goto LOOP;
}
}
return cluster;
}
/* Unlike enclosingClusterForNodes, this will only return a cluster
that directly contains the nodes, i.e. none of the nodes will
be found in any sub clusters. */
- (GKGraph*)clusterForNodes:(NSSet*)someNodes
{
GKGraph *cluster = [self enclosingClusterForNodes:someNodes];
for (GKGraph *subcluster in subgraphs)
if (subcluster.isCluster && [nodes intersectsSet:subcluster.nodes])
return nil;
return cluster;
}
(I actually wonder whether you meant clusterForNodes to do what
enclosingClusterForNodes does and given the uncertainty, it certainly
warrants a comment.)
> I thought __block variables are not on the heap until the block itself is
> copied?
That's the reason for the indirections. The compiler has to find the correct
location for the block variable. See <
http://clang.llvm.org/docs/Block-ABI-Apple.txt> section 2.3.3. (The
documentation doesn't like exactly right to me, but you can get the idea).
> A smart compiler could see that the block only exists or is used within a
> scope, so the __block variable will only ever be on the stack, so there
> should only be the single indirection at most?
I concede that a smart compiler could actually optimise the case, but to do
that, someone would have had to put in the effort to optimise the specific
case and when the usual use case for a __block variable is for a quite
different purpose, I don't see that happening any time soon.
> You do get an analyzer warning if you forget the __block modifier. It
> complains that you are capturing garbage since it is uninitialized.
Sure, I knew that, but you don't always run the analyser.
Anyway, I personally wouldn't use a block as you've used it and I'm not
convinced your algorithm needs to be recursive, so I've still yet to see a
legitimate use case for recursive blocks.
Kind regards,
Chris
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden