Many times I need to do things TWICE in a for loop. Simply I can set up a for loop with an iterator and go through it twice:
for (i = 0; i < 2; i++)
{
// Do stuff
}
Now I am interested in doing this as SIMPLY as I can, perhaps without an initializer or iterator? Are there any other, really simple and elegant, ways of achieving this?
This is elegant because it looks like a triangle; and triangles are elegant.
i = 0;
here: dostuff();
i++; if ( i == 1 ) goto here;
Encapsulate it in a function and call it twice.
void do_stuff() {
// Do Stuff
}
// .....
do_stuff();
do_stuff();
Note: if you use variables or parameters of the enclosing function in the stuff logic, you can pass them as arguments to the extracted do_stuff function.
If its only twice, and you want to avoid a loop, just write the darn thing twice.
statement1;
statement1; // (again)
If the loop is too verbose for you, you can also define an alias for it:
#define TWICE for (int _index = 0; _index < 2; _index++)
This would result into that code:
TWICE {
// Do Stuff
}
// or
TWICE
func();
I would only recommend to use this macro if you have to do this very often, I think else the plain for-loop is more readable.
Unfortunately, this is not for C, but for C++ only, but does exactly what you want:
Just include the header, and you can write something like this:
10 times {
// Do stuff
}
I'll try to rewrite it for C as well.
So, after some time, here's an approach that enables you to write the following in pure C:
2 times {
do_something()
}
Example:
You'll have to include this little thing as a simple header file (I always called the file extension.h). Then, you'll be able to write programs in the style of:
#include<stdio.h>
#include"extension.h"
int main(int argc, char** argv){
3 times printf("Hello.\n");
3 times printf("Score: 0 : %d\n", _);
2 times {
printf("Counting: ");
9 times printf("%d ", _);
printf("\n");
}
5 times {
printf("Counting up to %d: ", _);
_ times printf("%d ", _);
printf("\n");
}
return 0;
}
Features:
Simple notation of simple loops (in the style depicted above)
Counter is implicitly stored in a variable called _ (a simple underscore).
Nesting of loops allowed.
Restrictions (and how to (partially) circumvent them):
Works only for a certain number of loops (which is - "of course" - reasonable, since you only would want to use such a thing for "small" loops). Current implementation supports a maximum of 18 iterations (higher values result in undefined behaviour). Can be adjusted in header file by changing the size of array _A.
Only a certain nesting depth is allowed. Current implementation supports a nesting depth of 10. Can be adjusted by redefining the macro _Y.
Explanation:
You can see the full (=de-obfuscated) source-code here. Let's say we want to allow up to 18 loops.
Retrieving upper iteration bound: The basic idea is to have an array of chars that are initially all set to 0 (this is the array counterarray). If we issue a call to e.g. 2 times {do_it;}, the macro times shall set the second element of counterarray to 1 (i.e. counterarray[2] = 1). In C, it is possible to swap index and array name in such an assignment, so we can write 2[counterarray] = 1 to acchieve the same. This is exactly what the macro times does as first step. Then, we can later scan the array counterarray until we find an element that is not 0, but 1. The corresponding index is then the upper iteration bound. It is stored in variable searcher. Since we want to support nesting, we have to store the upper bound for each nesting depth separately, this is done by searchermax[depth]=searcher+1.
Adjusting current nesting depth: As said, we want to support nesting of loops, so we have to keep track of the current nesting depth (done in the variable depth). We increment it by one if we start such a loop.
The actual counter variable: We have a "variable" called _ that implicitly gets assigned the current counter. In fact, we store one counter for each nesting depth (all stored in the array counter. Then, _ is just another macro that retrieves the proper counter for the current nesting depth from this array.
The actual for loop: We take the for loop into parts:
We initialize the counter for the current nesting depth to 0 (done by counter[depth] = 0).
The iteration step is the most complicated part: We have to check if the loop at the current nesting depth has reached its end. If so, we have do update the nesting depth accordingly. If not, we have to increment the current nesting depth's counter by 1. The variable lastloop is 1 if this is the last iteration, otherwise 0, and we adjust the current nesting depth accordingly. The main problem here is that we have to write this as a sequence of expressions, all separated by commata, which requires us to write all these conditions in a very non-straight-forward way.
The "increment step" of the for loop consists of only one assignment, that increments the appropriate counter (i.e. the element of counter of the proper nesting depth) and assigns this value to our "counter variable" _.
What about this??
void DostuffFunction(){}
for (unsigned i = 0; i < 2; ++i, DostuffFunction());
Regards,
Pablo.
What abelenky said.
And if your { // Do stuff } is multi-line, make it a function, and call that function -- twice.
Many people suggest writing out the code twice, which is fine if the code is short. There is, however, a size of code block which would be awkward to copy but is not large enough to merit its own function (especially if that function would need an excessive number of parameters). My own normal idiom to run a loop 'n' times is
i = number_of_reps;
do
{
... whatever
} while(--i);
In some measure because I'm frequently coding for an embedded system where the up-counting loop is often inefficient enough to matter, and in some measure because it's easy to see the number of repetitions. Running things twice is a bit awkward because the most efficient coding on my target system
bit rep_flag;
rep_flag = 0;
do
{
...
} while(rep_flag ^= 1); /* Note: if loop runs to completion, leaves rep_flag clear */
doesn't read terribly well. Using a numeric counter suggests the number of reps can be varied arbitrarily, which in many instances won't be the case. Still, a numeric counter is probably the best bet.
As Edsger W. Dijkstra himself put it : "two or more, use a for". No need to be any simpler.
Another attempt:
for(i=2;i--;) /* Do stuff */
This solution has many benefits:
Shortest form possible, I claim (13 chars)
Still, readable
Includes initialization
The amount of repeats ("2") is visible in the code
Can be used as a toggle (1 or 0) inside the body e.g. for alternation
Works with single instruction, instruction body or function call
Flexible (doesn't have to be used only for "doing twice")
Dijkstra compliant ;-)
From comment:
for (i=2; i--; "Do stuff");
Use function:
func();
func();
Or use macro (not recommended):
#define DO_IT_TWICE(A) A; A
DO_IT_TWICE({ x+=cos(123); func(x); })
If your compiler supports this just put the declaration inside the for statement:
for (unsigned i = 0; i < 2; ++i)
{
// Do stuff
}
This is as elegant and efficient as it can be. Modern compilers can do loop unrolling and all that stuff, trust them. If you don't trust them, check the assembler.
And it has one little advantage to all other solutions, for everybody it just reads, "do it twice".
Assuming C++0x lambda support:
template <typename T> void twice(T t)
{
t();
t();
}
twice([](){ /*insert code here*/ });
Or:
twice([]()
{
/*insert code here*/
});
Which doesn't help you since you wanted it for C.
Good rule: three or more, do a for.
I think I read that in Code Complete, but I could be wrong. So in your case you don't need a for loop.
This is the shortest possible without preprocessor/template/duplication tricks:
for(int i=2; i--; ) /*do stuff*/;
Note that the decrement happens once right at the beginning, which is why this will loop precisely twice with the indices 1 and 0 as requested.
Alternatively you can write
for(int i=2; i--; /*do stuff*/) ;
But that's purely a difference of taste.
If what you are doing is somewhat complicated wrap it in a function and call that function twice? (This depends on how many local variables your do stuff code relies on).
You could do something like
void do_stuff(int i){
// do stuff
}
do_stuff(0);
do_stuff(1);
But this may get extremely ugly if you are working on a whole bunch of local variables.
//dostuff
stuff;
//dostuff (Attention I am doing the same stuff for the :**2nd** time)
stuff;
First, use a comment
/* Do the following stuff twice */
then,
1) use the for loop
2) write the statement twice, or
3) write a function and call the function twice
do not use macros, as earlier stated, macros are evil.
(My answer's almost a triangle)
What is elegance? How do you measure it? Is someone paying you to be elegant? If so how do they determine the dollar-to-elegance conversion?
When I ask myself, "how should this be written," I consider the priorities of the person paying me. If I'm being paid to write fast code, control-c, control-v, done. If I'm being paid to write code fast, well.. same thing. If I'm being paid to write code that occupies the smallest amount of space on the screen, I short the stock of my employer.
jump instruction is pretty slow,so if you write the lines one after the other,it would work faster,than writing a loop. but modern compilers are very,very smart and the optimizations are great (if they are allowed,of course). if you have turned on your compiler's optimizations,you don't care the way,you write it - with loop or not (:
EDIT : http://en.wikipedia.org/wiki/compiler_optimizations just take a look (:
Close to your example, elegant and efficient:
for (i = 2; i; --i)
{
/* Do stuff */
}
Here's why I'd recommend that approach:
It initializes the iterator to the number of iterations, which makes intuitive sense.
It uses decrement over increment so that the loop test expression is a comparison to zero (the "i;" can be interpreted as "is i true?" which in C means "is i non-zero"), which may optimize better on certain architectures.
It uses pre-decrement as opposed to post-decrement in the counting expression for the same reason (may optimize better).
It uses a for loop instead of do/while or goto or XOR or switch or macro or any other trick approach because readability and maintainability are more elegant and important than clever hacks.
It doesn't require you to duplicate the code for "Do stuff" so that you can avoid a loop. Duplicated code is an abomination and a maintenance nightmare.
If "Do stuff" is lengthy, move it into a function and give the compiler permission to inline it if beneficial. Then call the function from within the for loop.
I like Chris Case's solution (up here), but C language doesn't have default parameters.
My solution:
bool cy = false;
do {
// Do stuff twice
} while (cy = !cy);
If you want, you could do different things in the two cycle by checking the boolean variable (maybe by ternary operator).
void loopTwice (bool first = true)
{
// Recursion is your friend
if (first) {loopTwice(false);}
// Do Stuff
...
}
I'm sure there's a more elegant way, but this is simple to read, and pretty simply to write. There might even be a way to eliminate the bool parameter, but this is what I came up with in 20 seconds.
Related
so I'm slowly trying to learn C from scratch.
I'm at a point in the book I'm using where an exercise is proposed: use nested loops to find Pythagorean triplets. Now I'll show the code.
#include <stdio.h>
int main(void){
int lato1=1;
int lato2=1;
int ipotenusa=1;
for(;lato1 <= 500; lato1++){
for(;lato2 <= 500; lato2++){
for(;ipotenusa <= 500; ipotenusa++){
if (((lato1 * lato1)+(lato2 * lato2))==(ipotenusa*ipotenusa)){
printf("Tripletta %10d %10d %10d\n",lato1,lato2,ipotenusa);
}
}
}
}
return 0;
}
now, apart from terrible formatting and style, apart from the shi*t optimization,
the code as shown, doesnt work.
It only execute the inner most loop, and then the program ends.
If, however, I initialize each variable/counter inside each loop then it works.
Why?
I read that for loop initialization is valid even whitout no arguments (;;) but in this case I just wanted to initialize those variables before the loop, let's say because I wanted to access those value after the loop is done, it just doesn't seem to work like it's supposed to.
English is not my primary language so apologies in advance for any mystake.
Can somebody explain what is the problem?
Edit 1: So, I don't know if it was my bad English or something else.
I said, if I declare and initialize the variables before the loop, like in the code I've shown you, it only goes through the inner most loop (ipotenusa) and it does so with the following output values: 1 1 1 then 1 1 2 then 1 1 3 and so on, where the only increasing number is the last one (ipotenusa); AFTER we reach 1 1 500 the programs abruptily ends.
I then said that if I initialize the variables as normal, meaning inside the for loop instruction, then it works as intended.
Even if declared earlier there is NO reason it should't work. The variable's value it's supposed to increase. Up until now the only useful answer was to initialize a variable outside the loop but assign a value to it in the loop statement, but this is not at the end the answer I need, because I should be able to skip the initialization inside the loop statement altogether.
EDIT 2: I was wrong and You guys were right, language barrier (most likely foolishness, rather) was certainly the cause of the misunderstanding lol. Sorry and Thanks for the help!
You accidentally answered your own question:
...in this case I just wanted to initialize those variables before the loop, let's say because I wanted to access those value after the loop is done...
Think about the value of ipotenusa...or have your program print out the value of each variable at the start of each loop for debugging purposes. It'll look something like the following log.
lato1: 1
lato2: 1
ipotenusa: 1
ipotenusa: 2
ipotenusa: 3
ipotenusa: 4
ipotenusa: 5
lato2: 2
lato2: 3
lato2: 4
lato2: 5
lato1: 2
lato1: 3
lato1: 4
lato1: 5
The inner loops never "reset," because you're saving the value. You're not wrong on either count, but you've set up two requirements that conflict with each other, and the C runtime can only give you one.
Basically, lato2 and ipotenusa need to be initialized (but not necessarily declared) in their for statements, so that they're set up to run again.
int lato1=1;
int lato2;
int ipotenusa;
for(;lato1 <= 5; lato1++){
for(lato2 = 1;lato2 <= 5; lato2++){
for(ipotenusa = 1;ipotenusa <= 5; ipotenusa++){
if (((lato1 * lato1)+(lato2 * lato2))==(ipotenusa*ipotenusa)){
printf("Tripletta %10d %10d %10d\n",lato1,lato2,ipotenusa);
}
}
}
}
It's worth pointing out that, even though the specification might (or might not; I don't remember and am too fuzzy to look it up, right now) say that the loop variables only exist during the loop, I've never seen an implementation actually do that, so you'll see a lot of code out there that defines the variable inside of for and uses it after. It's probably not great and a static checker like lint might complain, but it's common enough that it'll pass most code reviewers, to give you a sense of whether it can be done.
Your code does exactly what you told it to do.
If you initialise lato2 with a value of 1, what makes you think that the initialisation will be repeated at the start of the inner for loop? Of course it isn't. You told the compiler that you didn't want it to be initialised again. After that loop executed the first time, lato2 has a value of 501, and it will keep that value forever.
Even if it hadn't produced a bug, putting the initialisation and the for loop so far apart is very, very bad style (wouldn't pass a code review in a professional setting and therefore would have to be changed).
for (int lato2 = 1; lato2 <= 500; ++lato2) is clear, obvious, and works.
One approach would be - declaring variables outside of the loop and initialize them inside. This way, you can access the variables after the loops.
#include <stdio.h>
int main(void){
int lato1, lato2, ipotenusa;
for(lato1=1; lato1 <= 500; lato1++){
for(lato2=1; lato2 <= 500; lato2++){
for(ipotenusa=1; ipotenusa <= 500; ipotenusa++){
if (((lato1 * lato1)+(lato2 * lato2))==(ipotenusa*ipotenusa)){
printf("Tripletta %10d %10d %10d\n",lato1,lato2,ipotenusa);
}
}
}
}
return 0;
}
You are using variables that are initialized outside of the for loops. Usually what happens is when we use inner loops(nested loops) we intended to initialize it with base value everytime but in your case it is never going to do that. Since you have initialized variable out side of the for loops so it will persist its value through out its life time of course which is main function in this case.
Example:
for (int i = 0; i < a[index]; i++) {
// do stuff
}
Would a[index] be read every time? If no, what if someone wanted to change the value at a[index] in the loop? I've never seen it myself, but does the compiler make such an assumption?
If the condition was instead i < val-2, would it be evaluated every time?
The compiler will perform optimizations normally when the system is not impacted by other parts of the program. So if you make changes inside the for loop on the condition parameter, the compiler will not optimize.
As mentioned, the compiler should read the array and check it before each iteration in your code snippet. You can optimize your code as follows, then it will read the array only once for loop condition checking.
int cond = a[index];
for (int i = 0; i < cond; i++) {
// do stuff
}
well, maybe.
A standards compliant compiler will produce code that behaves as-if it
is read every time.
If index and/or array are of storage class volatile the they will be re-evaluated every time.
If they are not and the loops content doesn't use them in a way that can be expected to modify their value the optimiser may decide to use a cached result instead.
Co does not store results of expressions in temporary variables. So, all expressions re evaluated in-place. Note that any for loop can be changed to a while loop:
for ( def_or_expr1 ; expr2 ; expr3 ) {
...
}
becomes:
def_or_expr1;
while ( expr2 ) {
...
cont:
expr3;
}
Update: continue in the for loop would be the same as goto cont; int the while loop above. I.e. expr3 is evaluated for every iteration.
The compiler can bascially apply any optimization it can proof not to change the program's essence. Describing full details would be too far for this, but in general, it can (and will) optimize:
a[index] is not changed in the loop: read once before loop and keep in a temp (e.g. register).
a[index] is changed in the loop: update the temp (register) with the new value, avoiding memory access (and the index calculations).
For this, the compiler must assume the array is not changed outside the visible control flow. This is typically the file being compiled (with all included files). For modern systems using link time optimization (LTO), this can be the whole final program - minus dynamic libraries.
Note this is a very brief description. Actually, the C standard defines pretty clear how a program has to be executed, so what/how the compiler may optimize.
If the array is changed, for example by an interrupt handler or another thread, things become complicated. Depending on your target, you need from volatile, atomic operations (stdatomic.h, since C11) up to thread locks/mutexes/semapores/etc. to control accesses to the share resource.
This is a function to get sum of the digits of a number:
int sumOfDigits(int n)
{
int sum=0; //line 1
if(n==0)
return sum;
else
{
sum=(n%10)+sumOfDigits(n/10); //line 2
// return sum; //line 3
}
}
While writing this code, I realized the scope of the local variables is local to each individual recursion of the function. So am I right in saying that if n=11111, 5 sum variables are created and pushed on the stack with each recursion? If this is correct then what is the benefit of using recursion when I can do it in normal function using loops, thus overwriting only one memory location? If I use pointers, recursion will probably take similar memory as a normal function.
Now my second question, even though this function gives me the correct result each time, I don't see how the recursions (other than the last one which returns 0) return values without uncommenting line 3. (using geany with gcc)
I'm new to programming, so please pardon any mistakes
So am I right in saying that if n=11111, 5 sum variables are created and pushed on the stack with each recursion?
Conceptually, but compilers may turn some forms of recursion into jumps/loops. E.g. a compiler that does tail call optimization may turn
void rec(int i)
{
if (i > 0) {
printf("Hello, level %d!\n", i);
rec(i - 1);
}
}
into the equivalent of
void loop(int i)
{
for (; i > 0; i--)
printf("Hello, level %d!\n", i);
}
because the recursive call is in tail position: when the call is made, the current invocation of rec has no more work to do except a return to its caller, so it might as well reuse its stack frame for the next recursive call.
If this is correct then what is the benefit of using recursion when I can do it in normal function using loops, thus overwriting only one memory location? If I use pointers, recursion will probably take similar memory as a normal function.
For this problem, recursion is a pretty bad fit, at least in C, because a loop is much more readable. There are problems, however, where recursion is easier to understand. Algorithms on tree structures are the prime example.
(Although every recursion can be emulated by a loop with an explicit stack, and then stack overflows can be more easily caught and handled.)
I don't understand the remark about pointers.
I don't see how the recursions (other than the last one which returns 0) return values without uncommenting line 3.
By chance. The program exhibits undefined behavior, so it may do anything, even return the correct answer.
So am I right in saying that if n=11111, 5 sum variables are created
and pushed on the stack with each recursion?
The recursion is 5 levels deep, so traditionally 5 stack frames will be eventually created (but read below!), each one of which will have space to hold a sum variable. So this is mostly correct in spirit.
If this is correct then what is the benefit of using recursion when I
can do it in normal function using loops, thus overwriting only one
memory location?
There are several reasons, which include:
it might be more natural to express an algorithm recursively; if the performance is acceptable, maintainability counts for a lot
simple recursive solutions typically do not keep state, which means they are trivially parallelizable, which is a major advantage in the multicore era
compiler optimizations frequently negate the drawbacks of recursion
I don't see how the recursions (other than the last one which returns
0) return values without uncommenting line 3.
It's undefined behavior to comment out line 3. Why would you do that?
Yes, the parameters and local variables are local to each invokation and this is usually achieved by creating a copy of each invokation variables set on the program stack. Yes, that consumes more memory compared to an implementation with a loop, but only if the problem can be solved with a loop and constant memory usage. Consider traversing a tree - you will have to store the tree elements somewhere - be it on the stack or in some other structure. Recursion advantage is it is easier to implement (but not always easier to debug).
If you comment return sum; in the second branch the behavior is undefined - anything can happen, expected behavior included. That's not what you should do.
I am inserting the snippet of code that is causing the problem. Please focus on the uncommented code, as that is the actual code. The commented out code was there to help me debug. Apologies for poor readability, but I decided to let the comments stay, in case anyone had a doubt as to how I arrived at my diagnosis of the problem.
void backProp(double back_prop_err, double x[])// x is the complete output of input layer neurons.
{
//j++;
//printf("\nA"); printf("\nj=%d",j);
error = out*(1-out)*back_prop_err;
printf("\nB:%20.18f",error);
//if(j==8)
//{
// printf("\nstart= %d, stop= %d",start, stop);
// temp=1;
//}
for(int i=start; i<= stop; i++)
{
// if(i==24)
// break;
// if(temp==1)
// {
// printf("\nstart= %d and stop= %d", start, stop); //temp=0;
// }
//j++;
//printf("\nC");
del_w[i] = c*error*x[i];
printf("\ndel_w[%d]=%20.18f",i,del_w[i]);
}
}
Please ignore the commented out sections. They were there to display stuff on the screen, so I could debug the code.
The Problem:
There are 3 classes, let's call them A, B and C. A has 24 objects, stored as an array. B has 10 objects, again in an array and C has only 1 object.
The above code is from the B class.
for class B's object[7], the value of start and stop (see above code) is 0 and 23, respectively. I have verified the same during runtime using the commented out pieces of code that you see above.
Yet, when the backProp function is called, at that particular for loop, an infinite loop is entered. The value of i keeps increasing without bound till DevC++ crashes. The commented out if(i==24) was put there to prevent that.
This only happens with class B's object[7]... Not with the previous 7 objects (object[0]...object[6]). For them, that particular loop starts and stops as per the set "start" and "stop" variables. Is it important that for those objects, "stop" is a small number (like 6 or 12 max)?
Class B's object[8] and object[9] also have stop = 23, which leads me to suspect that they too would face the same problem.
The Question: Why is this happening? start and stop variables are set. Why isn't the loop staying within those limits?
I have tried to keep this as concise as possible. Thank you for your efforts at reading this wall of a question.
EDIT: start and stop are private variables of class B (of which, the above function is a public function). They are set to their respective values using another public function, which I call from main.
j is somewhat embarrassing. It's a global static integer, initially set to 0. The reason I did this is so that I could count when class B's object[7] was accessing the backProp function. j gets incremented each time backProp is called, and as it's a static global, it acts as a counter so I can count till the object[7].
As per Oak's suggestion, I am putting up the link for the code here: http://pastebin.com/ftxBGs2y
Yeah, efforts are on to learn the DevC++ debugger. :P
I am pretty sure I don't have any problems with the dimensions of x. I will look into the matter again though.
My bet is that you are modifying i unintentionally when writing elements to del_w[]: perhaps the number of elements in the array is not large enough for what you are doing.
I say this because i and del_w could be close to each other on the stack but don't know for sure because I don't know how you allocated the memory for del_w.
Check the bounds of your arrays carefully, remembering that they are zero based.
It will not be anything funny in the for loop; you can trust the compiler!
But use a good debugger though or you'll waste so much time.
what is the alternate way of doing function of switch-case (and if-else) in c?
Function pointers are one alternative. Consider the following snippet that calls a function through a function pointer array:
#include <stdio.h>
void fn0(int n) { printf ("fn0, n = %d\n",n); }
void fn1(int n) { printf ("fn1, n = %d\n",n); }
void fn2(int n) { printf ("fn2, n = %d\n",n); }
void fn3(int n) { printf ("fn3, n = %d\n",n); }
static void (*fn[])(int) = {fn0, fn1, fn2, fn3};
int main(void) {
int i;
for (i = 0; i < 4; i++)
fn[i](10-i);
return 0;
}
This generates:
fn0, n = 10
fn1, n = 9
fn2, n = 8
fn3, n = 7
This sort of construct makes it very easy to implement things such as finite state machines where, instead of a massive switch statement or near-unmanageable nested if's, you can just use an integer state variable to index into an array of function pointers.
You could always use gotos... :-p
Function pointers and a semi implementation of the strategy pattern :)
.. though youll need some logic to determine which function to call
There are several different ways to handle conditional branch-and-switch scenarios in C.
The typical patterns, which you yourself mention, are switch( ) statements and if/else if/else groups. However, sometimes these flow control constructs are not the best choice for certain problems. Specifically cases such as:
High performance branching over a large domain
Branching on value domains only known at runtime
Changing the branch paths at runtime based on other conditions
In these cases, there are two patterns that I find helpful:
The Strategy pattern with a direct dispatch
The Strategy pattern with a chained dispatch
In the first approach, you map each value from your domain to a collection of function pointers. Each function handles a particular case (value) from your domain. This allows you to "jump" directly to the right handler for a particular case. This pattern works well when each case is separated from all the others and there is little or no overlapping logic.
In the second approach, you chain all of the dispatch methods together - and call each of them for all cases. Each dispatched method decides if it handles the case or not, and either returns immediately or performs some processing. This pattern is useful when there is overlap between the responsibilities of some of the handlers. It is somewhat less performant, since multiple handlers are invoked, and each decides whether it needs to perform its processing. However, this is one of the easier ways to deal with overlapping logic - the kind you could normally handle in a switch() statement with fall through (or jump) conditions.
You should only use one of these techniques if the problem really requires it, since they are less obvious to future developers and can introduce unnecessary complexity and maintenance problems if implemented poorly. It also makes your code more difficult to understand, over more common constructs like switch or if/else.