July 17, 2007
Taro Kawagishi wrote

> I think a more natural way to express the logic is to write the code as in listing 4.
> 
>     // listing 4
>     size_t pos = 0;
>     do {
>         pos = text.find(pattern, pos);
>     } while (pos != string::npos) {
>         cout << "pattern found at " << pos << "\n";
>         ++pos;
>     }
> 

Where is the problem with using `for'?

    for( size_t pos= 0
       ; ( pos = text.find(pattern, pos),  pos != text.length)
       ; pos++
       )
    {
      writefln( "pattern found at %s",  pos) ;
    }

-manfred
July 17, 2007
While we are at it, why not just this?

goto mid;
begin:
cc;
mid:
aa;
if (bb) goto begin;

Clear concise and simple, plus it is much closer to the actual machine logic, and so may imrpove performance as much as -1% ;)

BCS Wrote:

> Reply to Don,
> 
> > Walter uses 'goto' more than any other programmer I've ever seen.
> 
> I'd do this:
> 
> goto mid;
> while(bb)
> {
>   cc;
> mid:
>   aa;
> }
> 
> 

July 17, 2007
Here's a more generic version. This one was tested and shown to work.
Have fun with it!
 --downs
=======================================================================
import std.stdio, std.string;

/// Cond is
void doWhile(P, C, O)(lazy P pre, lazy C cond, lazy O post) {
  while (true) {
    static if (is(P==void delegate())) pre()(); else pre();
    if (!cond()) break;
    static if (is(O==void delegate())) post()(); else post();
  }
}

// these are the things stupid std.string forces us to do.
// Tango, with str.length==NOTFOUND, really picked the better approach.
int find(char[] str, char[] match, int offset) {
  auto res=std.string.find(str[offset..$], match);
  if (res==-1) return -1;
  return res+offset;
}

void main() {
  int pos=0;
  auto text="This interestingly works.";
  // Note the way we can switch between using brackets and not using them.
  doWhile(
    pos=text.find("i", pos),
    pos+1, /// equivalent to pos!=-1, except it also demonstrates
           /// that the conditional can be anything "if" can use.
    { writefln("Hit at ", pos); ++pos; }
  );
}
July 17, 2007
Reply to Tristam,

> While we are at it, why not just this?
> 
> goto mid;
> begin:
> cc;
> mid:
> aa;
> if (bb) goto begin;
> Clear concise and simple, plus it is much closer to the actual machine
> logic, and so may imrpove performance as much as -1% ;)
> 

While your point is relevant, the actual reason for doing it the way I pointed out is not performance, but the removal of duplicate source code. I am a firm believer in the assertion that anytime you have duplication of code[*], you have a bug waiting to happen.

Except for the goto, my example read reasonably clearly and does a reasonable job of describing what is intended. The original proposal and the other examples (except maybe the if()break; example) are not, IMHO, so clear. If you can think of a better way to show the intent, I'm interested.

*IIRC the XP folks will agree with me, however I'm only looking at code that is /exactly/ the same, not just abstractable to the same thing.


July 17, 2007
The point I was trying to make is that while any thing *can* be done through tricky code, the do {} while {} is such a common problem that I agree with the OP that it *should* have a distinct syntactical representation.
Intoducing such a basic syntax element to C/C++ at this stage would be nigh impossible, but D is young enough to adopt something like this, and something which simplifies syntax and readability is IMHO worth considering.

BCS Wrote:

> Reply to Tristam,
> 
> > While we are at it, why not just this?
> > 
> > goto mid;
> > begin:
> > cc;
> > mid:
> > aa;
> > if (bb) goto begin;
> > Clear concise and simple, plus it is much closer to the actual machine
> > logic, and so may imrpove performance as much as -1% ;)
> > 
> 
> While your point is relevant, the actual reason for doing it the way I pointed out is not performance, but the removal of duplicate source code. I am a firm believer in the assertion that anytime you have duplication of code[*], you have a bug waiting to happen.
> 
> Except for the goto, my example read reasonably clearly and does a reasonable job of describing what is intended. The original proposal and the other examples (except maybe the if()break; example) are not, IMHO, so clear. If you can think of a better way to show the intent, I'm interested.
> 
> *IIRC the XP folks will agree with me, however I'm only looking at code that is /exactly/ the same, not just abstractable to the same thing.
> 
> 

July 17, 2007
I also had this situation several times and I really like your suggestion.
July 17, 2007
"Taro Kawagishi" <tarok@acm.org> wrote in message news:f7hplb$1ovc$1@digitalmars.com...
> The advantage of the new construct will be seen if you have more complex
> statements within do and while blocks.
> I believe allowing this extended construct will be smooth since it will
> not break the existing code.
> I think D language would be a great fit to have this feature because the
> language seems to be still evolving.
>

I come across this scenario all the time, and it always strikes me as odd how common the issue is, yet how the language doesn't really provide a simple way to structure it.  Agreed.


July 17, 2007
I agree, too.

The goto thingy looks quite readable, but depending on how long your loop is it might not be in practice. Also it would be the first time I'd use goto.

The for-thingy as well as the doWhile mixin (which per se is *really* cool) loose some expressiveness. Imagine all code blocks would be longer. How long would you need to understand the meaning compared to the proposed construct?

Also I dont like making assignment-stuff in the condition-part of a while or for loop. I once tried it with this and if you have some not-too-short variable/function/method names you can easily get a while-condition thats about 5 lines long which is a pain in the eye.

Votes++;

// Henning

-- 
GPG Public Key: http://keyserver.ganneff.de:11371/pks/lookup?op=get&search=0xDDD6D36D41911851 Fingerprint: 344F 4072 F038 BB9E B35D  E6AB DDD6 D36D 4191 1851
July 17, 2007
downs Wrote:

> Taro Kawagishi wrote:
> > I think a more natural way to express the logic is to write the code as in listing 4.
> > 
> >     // listing 4
> >     size_t pos = 0;
> >     do {
> >         pos = text.find(pattern, pos);
> >     } while (pos != string::npos) {
> >         cout << "pattern found at " << pos << "\n";
> >         ++pos;
> >     }
> > 
> > The meaning of
> > 
> >     do {
> >         aa;
> >     } while (bb) {
> >         cc;
> >     }
> > 
> > is
> > 
> >     while (true) {
> >         aa;
> >         if (not bb) {
> >             break;
> >         }
> >         cc;
> >     }
> 
> void doWhile(void delegate() pre, lazy bool cond, void delegate() post) {
>    while (true) {
>      pre;
>      if (!cond()) break;
>      post;
>    }
> }
> 
> // listing 4, modified
> size_t pos=0;
> doWhile ({
>    pos=text.find(pattern, pos);
> }, pos!=string::npos, {
>    writefln("Pattern found at ", pos);
>    ++pos;
> });
> 
> Not tested, but should work.
> Have fun!

Being able to create templates that basically act like new keywords is one thing I love about D. I think your solution is better than any of the others posted.
July 17, 2007
I like your proposal very much. This pattern is very often, and your solution clearly shows the intended behaviour of the code. All the other "solutions" are more obscure and more unclear.

I also think extending D with this new construct is realy simple.

Votes++.

Taro Kawagishi escribió:
> Hello all,
> 
> every once in a while I feel uneasy when I find I can't fit my logic into a do-while or while loop in a concise way.
> Here is a C++ example:
> 
> void
> find_string_occurrences(const string& text, const string& pattern) {
> 
>     // listing 1
>     size_t pos = text.find(pattern, 0);
>     while (pos != string::npos) {
>         cout << "pattern found at " << pos << "\n";
>         ++pos;
>         pos = text.find(pattern, pos);
>     }
> 
> }
> 
> The way the code is written might look redundant in calling find() twice, but I think it is reasonable because you can test the loop condition only after you run function find() but here you can't use a do-while loop which doesn't allow you to place other statements after the condition statement.
> 
> I can write the same logic as in listing 2 and 3 below, but their meanings would be less clear than listing 1, because the looping condition is in the if statement together with the break statement in it, and you need to spot the if statement in the while body to understand it.
> 
>     // listing 2
>     size_t pos = 0;
>     while (true) {
>         pos = text.find(pattern, pos);
>         if (pos == string::npos) {
>             break;
>         }
>         cout << "pattern found at " << pos << "\n";
>         ++pos;
>     }
> 
>     // listing 3
>     size_t pos = 0;
>     do {
>         pos = text.find(pattern, pos);
>         if (pos == string::npos) {
>             break;
>         }
>         cout << "pattern found at " << pos << "\n";
>         ++pos;
>     } while (true);
> 
> I think a more natural way to express the logic is to write the code as in listing 4.
> 
>     // listing 4
>     size_t pos = 0;
>     do {
>         pos = text.find(pattern, pos);
>     } while (pos != string::npos) {
>         cout << "pattern found at " << pos << "\n";
>         ++pos;
>     }
> 
> The meaning of
> 
>     do {
>         aa;
>     } while (bb) {
>         cc;
>     }
> 
> is
> 
>     while (true) {
>         aa;
>         if (not bb) {
>             break;
>         }
>         cc;
>     }
> 
> and is a natural extension to both of
> 
>     do {
>         aa;
>     } while (bb);
> 
> and
> 
>     while (bb) {
>         cc;
>     }
> 
> The current while loop and do-while loop will be specialized forms of this general do-while loop.
> 
> The advantage of the new construct will be seen if you have more complex statements within do and while blocks.
> I believe allowing this extended construct will be smooth since it will not break the existing code.
> I think D language would be a great fit to have this feature because the language seems to be still evolving.
>