Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #29917 > unrolled thread

Favourite Pattern for Processing Zero, Once, Multiple

Started byShao Miller <sha0.miller@gmail.com>
First post2013-01-10 17:53 -0500
Last post2013-01-13 16:12 -0500
Articles 20 on this page of 21 — 9 participants

Back to article view | Back to comp.lang.c


Contents

  Favourite Pattern for Processing Zero, Once, Multiple Shao Miller <sha0.miller@gmail.com> - 2013-01-10 17:53 -0500
    Re: Favourite Pattern for Processing Zero, Once, Multiple "BartC" <bc@freeuk.com> - 2013-01-10 23:26 +0000
      Re: Favourite Pattern for Processing Zero, Once, Multiple Shao Miller <sha0.miller@gmail.com> - 2013-01-10 18:49 -0500
        Re: Favourite Pattern for Processing Zero, Once, Multiple "BartC" <bc@freeuk.com> - 2013-01-11 00:23 +0000
    Re: Favourite Pattern for Processing Zero, Once, Multiple Ben Bacarisse <ben.usenet@bsb.me.uk> - 2013-01-11 03:20 +0000
      Re: Favourite Pattern for Processing Zero, Once, Multiple Shao Miller <sha0.miller@gmail.com> - 2013-01-11 00:38 -0500
        Re: Favourite Pattern for Processing Zero, Once, Multiple Bart van Ingen Schenau <bart@ingen.ddns.info.invalid> - 2013-01-11 12:10 +0000
          Re: Favourite Pattern for Processing Zero, Once, Multiple Shao Miller <sha0.miller@gmail.com> - 2013-01-11 13:37 -0500
        Re: Favourite Pattern for Processing Zero, Once, Multiple "BartC" <bc@freeuk.com> - 2013-01-11 12:15 +0000
          Re: Favourite Pattern for Processing Zero, Once, Multiple Shao Miller <sha0.miller@gmail.com> - 2013-01-11 13:56 -0500
            Re: Favourite Pattern for Processing Zero, Once, Multiple Fred K <fred.l.kleinschmidt@gmail.com> - 2013-01-11 11:15 -0800
              Re: Favourite Pattern for Processing Zero, Once, Multiple Shao Miller <sha0.miller@gmail.com> - 2013-01-11 14:28 -0500
            Re: Favourite Pattern for Processing Zero, Once, Multiple Greg Martin <greg@softsprocket.com> - 2013-01-11 11:22 -0800
              Re: Favourite Pattern for Processing Zero, Once, Multiple Shao Miller <sha0.miller@gmail.com> - 2013-01-11 15:23 -0500
                Re: Favourite Pattern for Processing Zero, Once, Multiple Greg Martin <greg@softsprocket.com> - 2013-01-11 13:09 -0800
            Re: Favourite Pattern for Processing Zero, Once, Multiple "BartC" <bc@freeuk.com> - 2013-01-11 22:09 +0000
            Re: Favourite Pattern for Processing Zero, Once, Multiple Paul N <gw7rib@aol.com> - 2013-01-12 04:49 -0800
              Re: Favourite Pattern for Processing Zero, Once, Multiple Shao Miller <sha0.miller@gmail.com> - 2013-01-13 20:30 -0500
    Re: Favourite Pattern for Processing Zero, Once, Multiple glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2013-01-11 21:02 +0000
    Re: Favourite Pattern for Processing Zero, Once, Multiple Phil Carmody <thefatphil_demunged@yahoo.co.uk> - 2013-01-13 20:28 +0200
      Re: Favourite Pattern for Processing Zero, Once, Multiple Shao Miller <sha0.miller@gmail.com> - 2013-01-13 16:12 -0500

Page 1 of 2  [1] 2  Next page →


#29917 — Favourite Pattern for Processing Zero, Once, Multiple

FromShao Miller <sha0.miller@gmail.com>
Date2013-01-10 17:53 -0500
SubjectFavourite Pattern for Processing Zero, Once, Multiple
Message-ID<kcngpa$2jl$1@dont-email.me>
Suppose you have a function 'bar' that returns a value that means one of:
   - Do 'foo' zero times
   - Do 'foo' one time
   - Do 'foo' more than one time

What's your favourite way of handling such a value?  For example:

   while ((more = bar()) != cv_zero_times) {
       /* Do it at least once */
       foo();

       /* Do it more than once? */
       if (more != cv_more_times)
         break;
     }

- Shao Miller
-- 
"Thank you for the kind words; those are the kind of words I like to hear.

Cheerily,"  -- Richard Harter

[toc] | [next] | [standalone]


#29922

From"BartC" <bc@freeuk.com>
Date2013-01-10 23:26 +0000
Message-ID<f7IHs.6$wT7.5@fx02.fr7>
In reply to#29917

"Shao Miller" <sha0.miller@gmail.com> wrote in message 
news:kcngpa$2jl$1@dont-email.me...
> Suppose you have a function 'bar' that returns a value that means one of:
>   - Do 'foo' zero times
>   - Do 'foo' one time
>   - Do 'foo' more than one time
>
> What's your favourite way of handling such a value?

Obvious return values would be (0, 1, 2), or (0, N) (or just N) if the 
actual number of times is being specified.

-- 
bartc 

[toc] | [prev] | [next] | [standalone]


#29924

FromShao Miller <sha0.miller@gmail.com>
Date2013-01-10 18:49 -0500
Message-ID<kcnk1e$kmq$1@dont-email.me>
In reply to#29922
On 1/10/2013 18:26, BartC wrote:
>
>
> "Shao Miller" <sha0.miller@gmail.com> wrote in message
> news:kcngpa$2jl$1@dont-email.me...
>> Suppose you have a function 'bar' that returns a value that means one of:
>>   - Do 'foo' zero times
>>   - Do 'foo' one time
>>   - Do 'foo' more than one time
>>
>> What's your favourite way of handling such a value?   For example:
>>
>>   while ((more = bar()) != cv_zero_times) {
>>       /* Do it at least once */
>>       foo();
>>
>>       /* Do it more than once? */
>>       if (more != cv_more_times)
>>         break;
>>     }
>
> Obvious return values would be (0, 1, 2), or (0, N) (or just N) if the
> actual number of times is being specified.
>

Agreed.

And what might be the pattern, in C, that you might use in order to 
handle the value and to call 'foo' the right number of times?  As 
another example:

   while (1) {
       switch (bar()) {
           case cv_zero_times:
           /* Exit switch */
           break;

           case cv_more_times:
           foo();
           /* Continue loop */
           continue;

           default:
           /* One time */
           foo();
         }
       /* Exit loop */
       break;
     }

- Shao Miller
-- 
"Thank you for the kind words; those are the kind of words I like to hear.

Cheerily,"  -- Richard Harter

[toc] | [prev] | [next] | [standalone]


#29927

From"BartC" <bc@freeuk.com>
Date2013-01-11 00:23 +0000
Message-ID<QYIHs.2687$Ue2.2558@fx30.fr7>
In reply to#29924
"Shao Miller" <sha0.miller@gmail.com> wrote in message
news:kcnk1e$kmq$1@dont-email.me...
> On 1/10/2013 18:26, BartC wrote:

>> Obvious return values would be (0, 1, 2), or (0, N) (or just N) if the
>> actual number of times is being specified.
>>
>
> Agreed.
>
> And what might be the pattern, in C, that you might use in order to handle
> the value and to call 'foo' the right number of times?  As another
> example:

>   while (1) {
>       switch (bar()) {

OK, you want to know what is actually done with such a value.

I like using switch when decoding multiple values of the same expression. So
your second example is better, IMO, when your bar() function returns one of 
three possibilities.

-- 
Bartc 

[toc] | [prev] | [next] | [standalone]


#29932

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2013-01-11 03:20 +0000
Message-ID<0.e4da14736427397ca6e1.20130111032010GMT.878v80quc5.fsf@bsb.me.uk>
In reply to#29917
Shao Miller <sha0.miller@gmail.com> writes:

> Suppose you have a function 'bar' that returns a value that means one of:
>   - Do 'foo' zero times
>   - Do 'foo' one time
>   - Do 'foo' more than one time
>
> What's your favourite way of handling such a value?  For example:
>
>   while ((more = bar()) != cv_zero_times) {
>       /* Do it at least once */
>       foo();
>
>       /* Do it more than once? */
>       if (more != cv_more_times)
>         break;
>     }

I'd re-think the whole thing.  It's confusing to me since a return of
"more than one time" does not seem to me any such thing (unless you've
got your loop wrong).  It seems to mean "do it once and call bar again"
which is messy because it implies an awkward linkage between bar and
foo.

Does this crop up for real?  I'd try to find a cleaner way to write the
whole bar() + foo() interaction.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#29933

FromShao Miller <sha0.miller@gmail.com>
Date2013-01-11 00:38 -0500
Message-ID<kco8gq$mao$1@dont-email.me>
In reply to#29932
On 1/10/2013 22:20, Ben Bacarisse wrote:
> Shao Miller <sha0.miller@gmail.com> writes:
>
>> Suppose you have a function 'bar' that returns a value that means one of:
>>    - Do 'foo' zero times
>>    - Do 'foo' one time
>>    - Do 'foo' more than one time
>>
>> What's your favourite way of handling such a value?  For example:
>>
>>    while ((more = bar()) != cv_zero_times) {
>>        /* Do it at least once */
>>        foo();
>>
>>        /* Do it more than once? */
>>        if (more != cv_more_times)
>>          break;
>>      }
>
> I'd re-think the whole thing.  It's confusing to me since a return of
> "more than one time" does not seem to me any such thing (unless you've
> got your loop wrong).  It seems to mean "do it once and call bar again"
> which is messy because it implies an awkward linkage between bar and
> foo.
>
> Does this crop up for real?  I'd try to find a cleaner way to write the
> whole bar() + foo() interaction.
>

Thanks, BartC, for your response (I sent you an e-mail, but "no such user").

Thanks, Ben, for your response.  Yes, the linkage is awkward!

Yes, 'foo' was just an example of a "do-something."  The actual problem 
that got me thinking about this is a bit boring, but I wondered if 
anyone might have a pattern to suggest.

Consider 'bar' as translating a sequence of characters, one at a time. 
The caller uses it for translation, but it's the caller's responsibility 
to do something useful with the translated characters.

Sometimes 'bar' will emit no translated characters, but simply track 
some state.  ("Deal with zero translated characters.")

Sometimes 'bar' will emit a single translated character that's a simple 
mapping from the input character.  ("Deal with one translated character.")

Sometimes 'bar' will have multiple characters to emit, and the caller 
needs to call it multiple times to get all of the characters.  ("Here's 
one translated character, but call me again because I have more.")

Could be useful for escape sequences: "123${special}ABC" where the '$' 
through until the 'l' wouldn't emit anything, but then the subsequent 
'}' would cause some special sequence to be emitted, where 'bar' would 
know what to emit, but would have to be queried repeatedly until it 
finished emitting the special sequence.

One way to deal with this would be to pass a call-back and context to 
'bar' so that it could do the emitting itself, but that requires the 
programmer to create such a call-back function.

Another way is to use EOF-style, and the case of a single character 
output means that 'bar' is always called a second time simply to return 
end-of-sequence, which thus suffers a bit of a performance drawback for 
that case.

So I thought it was a bit of an interesting challenge and I wonder what 
strategies folks might've or might come up with, as a general pattern.

Thanks for your time.

-- 
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.

Cheerily,"  -- Richard Harter

[toc] | [prev] | [next] | [standalone]


#29941

FromBart van Ingen Schenau <bart@ingen.ddns.info.invalid>
Date2013-01-11 12:10 +0000
Message-ID<kcovf6$tbj$1@dont-email.me>
In reply to#29933
On Fri, 11 Jan 2013 00:38:33 -0500, Shao Miller wrote:

> One way to deal with this would be to pass a call-back and context to
> 'bar' so that it could do the emitting itself, but that requires the
> programmer to create such a call-back function.

This might be a good option, but it depends on how well it fits in the 
overall application design.

> 
> Another way is to use EOF-style, and the case of a single character
> output means that 'bar' is always called a second time simply to return
> end-of-sequence, which thus suffers a bit of a performance drawback for
> that case.

This would be my first choice, before discriminating between 1 and 
multiple values to return.
I would make that discrimination only if actual profiling measurements 
have shown that the additional call really is a performance bottleneck.

> 
> So I thought it was a bit of an interesting challenge and I wonder what
> strategies folks might've or might come up with, as a general pattern.
> 
> Thanks for your time.
> 
> --
> - Shao Miller

Bart v Ingen Schenau

[toc] | [prev] | [next] | [standalone]


#29950

FromShao Miller <sha0.miller@gmail.com>
Date2013-01-11 13:37 -0500
Message-ID<kcpm60$a0k$1@dont-email.me>
In reply to#29941
On 1/11/2013 07:10, Bart van Ingen Schenau wrote:
> On Fri, 11 Jan 2013 00:38:33 -0500, Shao Miller wrote:
>
>> One way to deal with this would be to pass a call-back and context to
>> 'bar' so that it could do the emitting itself, but that requires the
>> programmer to create such a call-back function.
>
> This might be a good option, but it depends on how well it fits in the
> overall application design.
>
>>
>> Another way is to use EOF-style, and the case of a single character
>> output means that 'bar' is always called a second time simply to return
>> end-of-sequence, which thus suffers a bit of a performance drawback for
>> that case.
>
> This would be my first choice, before discriminating between 1 and
> multiple values to return.
> I would make that discrimination only if actual profiling measurements
> have shown that the additional call really is a performance bottleneck.
>

Yeah the call-back strategy has added complexity, but my natural 
inclination would be towards this same strategy as you've stated you 
prefer, with the same rationale. :)  Thanks for the feed-back!

>>
>> So I thought it was a bit of an interesting challenge and I wonder what
>> strategies folks might've or might come up with, as a general pattern.

-- 
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.

Cheerily,"  -- Richard Harter

[toc] | [prev] | [next] | [standalone]


#29943

From"BartC" <bc@freeuk.com>
Date2013-01-11 12:15 +0000
Message-ID<uoTHs.8028$MG6.2033@fx32.fr7>
In reply to#29933
"Shao Miller" <sha0.miller@gmail.com> wrote in message
news:kco8gq$mao$1@dont-email.me...
> On 1/10/2013 22:20, Ben Bacarisse wrote:

>> Does this crop up for real?  I'd try to find a cleaner way to write the
>> whole bar() + foo() interaction.

That's the key I think (see below).

> Thanks, BartC, for your response (I sent you an e-mail, but "no such
> user").

It was a valid email at one time (Try using bcas instead of bc)

> Sometimes 'bar' will have multiple characters to emit, and the caller
> needs to call it multiple times to get all of the characters.  ("Here's
> one translated character, but call me again because I have more.")
>
> Could be useful for escape sequences: "123${special}ABC" where the '$'
> through until the 'l' wouldn't emit anything, but then the subsequent '}'
> would cause some special sequence to be emitted, where 'bar' would know
> what to emit, but would have to be queried repeatedly until it finished
> emitting the special sequence.

At first glance this seems perfectly straightforward: bar is just called
repeatedly until the 'EOF' marker you mention is returned. In this case,
bar() returns the next character in the sequence, rather than some code. If
the "123" in your example was consumed with no output, then bar wouldn't
return until there was something to return, in this case the first character
of whatever replaces "${special}".

But it gets more complicated when you have to consider where this input
string comes from. There might be some global state containing the input
stream, the current position in that stream, and the current position in any
translation string. Or that state might be contained inside bar().

Or perhaps the caller might supply bar() with the next input character (and
bar() needs some look-ahead to operate properly). Or a pointer to a struct
containing the state (so that bar() can be called from different places, all
with their own strings to translate).

> So I thought it was a bit of an interesting challenge and I wonder what
> strategies folks might've or might come up with, as a general pattern.

It's not clear what the roles of bar() and foo() are. Maybe one of those 
returns the next translated character, but some more information is needed. 
The whole thing seems a bit like a tokeniser, or at least has some of the 
same problems to be solved.

-- 
Bartc
 

[toc] | [prev] | [next] | [standalone]


#29951

FromShao Miller <sha0.miller@gmail.com>
Date2013-01-11 13:56 -0500
Message-ID<kcpn8m$gvs$1@dont-email.me>
In reply to#29943
On 1/11/2013 07:15, BartC wrote:
> "Shao Miller" <sha0.miller@gmail.com> wrote in message
> news:kco8gq$mao$1@dont-email.me...
>> On 1/10/2013 22:20, Ben Bacarisse wrote:
>
>>> Does this crop up for real?  I'd try to find a cleaner way to write the
>>> whole bar() + foo() interaction.
>
> That's the key I think (see below).
>
>> Sometimes 'bar' will have multiple characters to emit, and the caller
>> needs to call it multiple times to get all of the characters.  ("Here's
>> one translated character, but call me again because I have more.")
>>
>> Could be useful for escape sequences: "123${special}ABC" where the '$'
>> through until the 'l' wouldn't emit anything, but then the subsequent '}'
>> would cause some special sequence to be emitted, where 'bar' would know
>> what to emit, but would have to be queried repeatedly until it finished
>> emitting the special sequence.
>
> At first glance this seems perfectly straightforward: bar is just called
> repeatedly until the 'EOF' marker you mention is returned. In this case,
> bar() returns the next character in the sequence, rather than some code. If
> the "123" in your example was consumed with no output, then bar wouldn't
> return until there was something to return, in this case the first
> character
> of whatever replaces "${special}".
>
> But it gets more complicated when you have to consider where this input
> string comes from. There might be some global state containing the input
> stream, the current position in that stream, and the current position in
> any
> translation string. Or that state might be contained inside bar().
>
> Or perhaps the caller might supply bar() with the next input character (and
> bar() needs some look-ahead to operate properly). Or a pointer to a struct
> containing the state (so that bar() can be called from different places,
> all
> with their own strings to translate).
>
>> So I thought it was a bit of an interesting challenge and I wonder what
>> strategies folks might've or might come up with, as a general pattern.
>
> It's not clear what the roles of bar() and foo() are. Maybe one of those
> returns the next translated character, but some more information is
> needed. The whole thing seems a bit like a tokeniser, or at least has
> some of the same problems to be solved.
>

Yeah I was trying to abstract away the details and ask about a general 
pattern (since that's what I'm interested in), but maybe the code 
example was not illustrative enough. :)

For the subsequent translation scenario I tried to describe, the caller 
is responsible for getting a single input character 'ic'.  However they 
do it should be opaque to the translating function, 'bar'.  The caller 
calls 'bar' to translate 'ic' to '*oc'.

   extern return_type bar(state_type state, char ic, char * oc);

'bar' might not emit any output character '*oc' if it's not yet ready. 
In that case, the caller shouldn't work with '*oc'; shouldn't send it 
wherever output is going.

'bar' might emit '*oc' and have nothing more to emit until processing 
the next 'ic' or beyond.

'bar' might emit '*oc' and inform the caller that there are more output 
characters pending, so the caller should call 'bar' again until they've 
been consumed.  In this case, 'ic' is ignored for subsequent calls to 
'bar' as 'bar' already knows what sequence it wishes to emit based on 
the 'ic' that triggered it.

'foo' was really just a place-holder for "something the caller does with 
the results of 'bar'".  This might be to put the output characters in a 
buffer or to send them to a stream.

I'm interested in general C patterns for this kind of scenario without 
getting too distracted by this particular example of "translating 
characters".  Having said that, maybe working with this example scenario 
is a better idea.

-- 
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.

Cheerily,"  -- Richard Harter

[toc] | [prev] | [next] | [standalone]


#29953

FromFred K <fred.l.kleinschmidt@gmail.com>
Date2013-01-11 11:15 -0800
Message-ID<181d1d08-2d48-4f74-88de-1fe73d483ab3@googlegroups.com>
In reply to#29951
On Friday, January 11, 2013 10:56:21 AM UTC-8, Shao Miller wrote:
> On 1/11/2013 07:15, BartC wrote:
> 
> > "Shao Miller" <sha0.miller@gmail.com> wrote in message
> 
> > news:kco8gq$mao$1@dont-email.me...
> 
> >> On 1/10/2013 22:20, Ben Bacarisse wrote:
> 
> >
> 
> >>> Does this crop up for real?  I'd try to find a cleaner way to write the
> 
> >>> whole bar() + foo() interaction.
> 
> >
> 
> > That's the key I think (see below).
> 
> >
> 
> >> Sometimes 'bar' will have multiple characters to emit, and the caller
> 
> >> needs to call it multiple times to get all of the characters.  ("Here's
> 
> >> one translated character, but call me again because I have more.")
> 
> >>
> 
> >> Could be useful for escape sequences: "123${special}ABC" where the '$'
> 
> >> through until the 'l' wouldn't emit anything, but then the subsequent '}'
> 
> >> would cause some special sequence to be emitted, where 'bar' would know
> 
> >> what to emit, but would have to be queried repeatedly until it finished
> 
> >> emitting the special sequence.
> 
> >
> 
> > At first glance this seems perfectly straightforward: bar is just called
> 
> > repeatedly until the 'EOF' marker you mention is returned. In this case,
> 
> > bar() returns the next character in the sequence, rather than some code. If
> 
> > the "123" in your example was consumed with no output, then bar wouldn't
> 
> > return until there was something to return, in this case the first
> 
> > character
> 
> > of whatever replaces "${special}".
> 
> >
> 
> > But it gets more complicated when you have to consider where this input
> 
> > string comes from. There might be some global state containing the input
> 
> > stream, the current position in that stream, and the current position in
> 
> > any
> 
> > translation string. Or that state might be contained inside bar().
> 
> >
> 
> > Or perhaps the caller might supply bar() with the next input character (and
> 
> > bar() needs some look-ahead to operate properly). Or a pointer to a struct
> 
> > containing the state (so that bar() can be called from different places,
> 
> > all
> 
> > with their own strings to translate).
> 
> >
> 
> >> So I thought it was a bit of an interesting challenge and I wonder what
> 
> >> strategies folks might've or might come up with, as a general pattern.
> 
> >
> 
> > It's not clear what the roles of bar() and foo() are. Maybe one of those
> 
> > returns the next translated character, but some more information is
> 
> > needed. The whole thing seems a bit like a tokeniser, or at least has
> 
> > some of the same problems to be solved.
> 
> >
> 
> 
> 
> Yeah I was trying to abstract away the details and ask about a general 
> 
> pattern (since that's what I'm interested in), but maybe the code 
> 
> example was not illustrative enough. :)
> 
> 
> 
> For the subsequent translation scenario I tried to describe, the caller 
> 
> is responsible for getting a single input character 'ic'.  However they 
> 
> do it should be opaque to the translating function, 'bar'.  The caller 
> 
> calls 'bar' to translate 'ic' to '*oc'.
> 
> 
> 
>    extern return_type bar(state_type state, char ic, char * oc);
> 
> 
> 
> 'bar' might not emit any output character '*oc' if it's not yet ready. 
> 
> In that case, the caller shouldn't work with '*oc'; shouldn't send it 
> 
> wherever output is going.
> 
> 
> 
> 'bar' might emit '*oc' and have nothing more to emit until processing 
> 
> the next 'ic' or beyond.
> 
> 
> 
> 'bar' might emit '*oc' and inform the caller that there are more output 
> 
> characters pending, so the caller should call 'bar' again until they've 
> 
> been consumed.  In this case, 'ic' is ignored for subsequent calls to 
> 
> 'bar' as 'bar' already knows what sequence it wishes to emit based on 
> 
> the 'ic' that triggered it.

Ouch! shades of strtok()
This design is not re-entrant-safe, and definitely not threadsafe.


> 
> 
> 
> 'foo' was really just a place-holder for "something the caller does with 
> 
> the results of 'bar'".  This might be to put the output characters in a 
> 
> buffer or to send them to a stream.
> 
> 
> 
> I'm interested in general C patterns for this kind of scenario without 
> 
> getting too distracted by this particular example of "translating 
> 
> characters".  Having said that, maybe working with this example scenario 
> 
> is a better idea.
> 
> 

I would consider something like this:

bar(state_type state, char ic, char * oc, MyCallback foo); 

where bar internally calls foo the requisite number of times.
Perhaps in this scenario the oc parameter is not even needed.
-- 
Fred K

[toc] | [prev] | [next] | [standalone]


#29956

FromShao Miller <sha0.miller@gmail.com>
Date2013-01-11 14:28 -0500
Message-ID<kcpp4m$t5j$1@dont-email.me>
In reply to#29953
On 1/11/2013 14:15, Fred K wrote:
> On Friday, January 11, 2013 10:56:21 AM UTC-8, Shao Miller wrote:
>> On 1/11/2013 07:15, BartC wrote:
>>
>>> "Shao Miller" <sha0.miller@gmail.com> wrote in message
>>
>>> news:kco8gq$mao$1@dont-email.me...
>>
>>>> On 1/10/2013 22:20, Ben Bacarisse wrote:
>>
>>>
>>
>>>>> Does this crop up for real?  I'd try to find a cleaner way to write the
>>
>>>>> whole bar() + foo() interaction.
>>
>>>
>>
>>> That's the key I think (see below).
>>
>>>
>>
>>>> Sometimes 'bar' will have multiple characters to emit, and the caller
>>
>>>> needs to call it multiple times to get all of the characters.  ("Here's
>>
>>>> one translated character, but call me again because I have more.")
>>
>>>>
>>
>>>> Could be useful for escape sequences: "123${special}ABC" where the '$'
>>
>>>> through until the 'l' wouldn't emit anything, but then the subsequent '}'
>>
>>>> would cause some special sequence to be emitted, where 'bar' would know
>>
>>>> what to emit, but would have to be queried repeatedly until it finished
>>
>>>> emitting the special sequence.
>>
>>>
>>
>>> At first glance this seems perfectly straightforward: bar is just called
>>
>>> repeatedly until the 'EOF' marker you mention is returned. In this case,
>>
>>> bar() returns the next character in the sequence, rather than some code. If
>>
>>> the "123" in your example was consumed with no output, then bar wouldn't
>>
>>> return until there was something to return, in this case the first
>>
>>> character
>>
>>> of whatever replaces "${special}".
>>
>>>
>>
>>> But it gets more complicated when you have to consider where this input
>>
>>> string comes from. There might be some global state containing the input
>>
>>> stream, the current position in that stream, and the current position in
>>
>>> any
>>
>>> translation string. Or that state might be contained inside bar().
>>
>>>
>>
>>> Or perhaps the caller might supply bar() with the next input character (and
>>
>>> bar() needs some look-ahead to operate properly). Or a pointer to a struct
>>
>>> containing the state (so that bar() can be called from different places,
>>
>>> all
>>
>>> with their own strings to translate).
>>
>>>
>>
>>>> So I thought it was a bit of an interesting challenge and I wonder what
>>
>>>> strategies folks might've or might come up with, as a general pattern.
>>
>>>
>>
>>> It's not clear what the roles of bar() and foo() are. Maybe one of those
>>
>>> returns the next translated character, but some more information is
>>
>>> needed. The whole thing seems a bit like a tokeniser, or at least has
>>
>>> some of the same problems to be solved.
>>
>>>
>>
>>
>>
>> Yeah I was trying to abstract away the details and ask about a general
>>
>> pattern (since that's what I'm interested in), but maybe the code
>>
>> example was not illustrative enough. :)
>>
>>
>>
>> For the subsequent translation scenario I tried to describe, the caller
>>
>> is responsible for getting a single input character 'ic'.  However they
>>
>> do it should be opaque to the translating function, 'bar'.  The caller
>>
>> calls 'bar' to translate 'ic' to '*oc'.
>>
>>
>>
>>     extern return_type bar(state_type state, char ic, char * oc);
>>
>>
>>
>> 'bar' might not emit any output character '*oc' if it's not yet ready.
>>
>> In that case, the caller shouldn't work with '*oc'; shouldn't send it
>>
>> wherever output is going.
>>
>>
>>
>> 'bar' might emit '*oc' and have nothing more to emit until processing
>>
>> the next 'ic' or beyond.
>>
>>
>>
>> 'bar' might emit '*oc' and inform the caller that there are more output
>>
>> characters pending, so the caller should call 'bar' again until they've
>>
>> been consumed.  In this case, 'ic' is ignored for subsequent calls to
>>
>> 'bar' as 'bar' already knows what sequence it wishes to emit based on
>>
>> the 'ic' that triggered it.
>
> Ouch! shades of strtok()
> This design is not re-entrant-safe, and definitely not threadsafe.
>

I meant for that to be in the 'state' parameter, shown above. :)

>
>>
>>
>>
>> 'foo' was really just a place-holder for "something the caller does with
>>
>> the results of 'bar'".  This might be to put the output characters in a
>>
>> buffer or to send them to a stream.
>>
>>
>>
>> I'm interested in general C patterns for this kind of scenario without
>>
>> getting too distracted by this particular example of "translating
>>
>> characters".  Having said that, maybe working with this example scenario
>>
>> is a better idea.
>>
>>
>
> I would consider something like this:
>
> bar(state_type state, char ic, char * oc, MyCallback foo);
>
> where bar internally calls foo the requisite number of times.
> Perhaps in this scenario the oc parameter is not even needed.
>

Right, that was one of the possibilities I'd mentioned upthread.  Just 
out of curiosity, does this call-back strategy score special points as 
opposed to other strategies (such as repeated calls to 'bar' until 
observing an "end-of-sequence" value), or is it roughly a matter of 
individual preference, for you?

Thanks for the feed-back!

-- 
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.

Cheerily,"  -- Richard Harter

[toc] | [prev] | [next] | [standalone]


#29954

FromGreg Martin <greg@softsprocket.com>
Date2013-01-11 11:22 -0800
Message-ID<PDZHs.24366$6a5.2147@newsfe14.iad>
In reply to#29951
On 13-01-11 10:56 AM, Shao Miller wrote:
> On 1/11/2013 07:15, BartC wrote:
>> "Shao Miller" <sha0.miller@gmail.com> wrote in message
>> news:kco8gq$mao$1@dont-email.me...
>>> On 1/10/2013 22:20, Ben Bacarisse wrote:
>>
>>>> Does this crop up for real?  I'd try to find a cleaner way to write the
>>>> whole bar() + foo() interaction.
>>
>> That's the key I think (see below).
>>
>>> Sometimes 'bar' will have multiple characters to emit, and the caller
>>> needs to call it multiple times to get all of the characters.  ("Here's
>>> one translated character, but call me again because I have more.")
>>>
>>> Could be useful for escape sequences: "123${special}ABC" where the '$'
>>> through until the 'l' wouldn't emit anything, but then the subsequent
>>> '}'
>>> would cause some special sequence to be emitted, where 'bar' would know
>>> what to emit, but would have to be queried repeatedly until it finished
>>> emitting the special sequence.
>>
>> At first glance this seems perfectly straightforward: bar is just called
>> repeatedly until the 'EOF' marker you mention is returned. In this case,
>> bar() returns the next character in the sequence, rather than some
>> code. If
>> the "123" in your example was consumed with no output, then bar wouldn't
>> return until there was something to return, in this case the first
>> character
>> of whatever replaces "${special}".
>>
>> But it gets more complicated when you have to consider where this input
>> string comes from. There might be some global state containing the input
>> stream, the current position in that stream, and the current position in
>> any
>> translation string. Or that state might be contained inside bar().
>>
>> Or perhaps the caller might supply bar() with the next input character
>> (and
>> bar() needs some look-ahead to operate properly). Or a pointer to a
>> struct
>> containing the state (so that bar() can be called from different places,
>> all
>> with their own strings to translate).
>>
>>> So I thought it was a bit of an interesting challenge and I wonder what
>>> strategies folks might've or might come up with, as a general pattern.
>>
>> It's not clear what the roles of bar() and foo() are. Maybe one of those
>> returns the next translated character, but some more information is
>> needed. The whole thing seems a bit like a tokeniser, or at least has
>> some of the same problems to be solved.
>>
>
> Yeah I was trying to abstract away the details and ask about a general
> pattern (since that's what I'm interested in), but maybe the code
> example was not illustrative enough. :)
>
> For the subsequent translation scenario I tried to describe, the caller
> is responsible for getting a single input character 'ic'.  However they
> do it should be opaque to the translating function, 'bar'.  The caller
> calls 'bar' to translate 'ic' to '*oc'.
>
>    extern return_type bar(state_type state, char ic, char * oc);
>
> 'bar' might not emit any output character '*oc' if it's not yet ready.
> In that case, the caller shouldn't work with '*oc'; shouldn't send it
> wherever output is going.
>
> 'bar' might emit '*oc' and have nothing more to emit until processing
> the next 'ic' or beyond.
>
> 'bar' might emit '*oc' and inform the caller that there are more output
> characters pending, so the caller should call 'bar' again until they've
> been consumed.  In this case, 'ic' is ignored for subsequent calls to
> 'bar' as 'bar' already knows what sequence it wishes to emit based on
> the 'ic' that triggered it.
>
> 'foo' was really just a place-holder for "something the caller does with
> the results of 'bar'".  This might be to put the output characters in a
> buffer or to send them to a stream.
>
> I'm interested in general C patterns for this kind of scenario without
> getting too distracted by this particular example of "translating
> characters".  Having said that, maybe working with this example scenario
> is a better idea.
>

I found it a little difficult to grasp the initial scenario because of 
the magical occurrences going on in the functions. I think that to 
discuss patterns in any language the example needs to be have enough 
detail to represent the problem space. When I looked at your first post 
I thought you working on some strange sort of iterator but now it looks 
more like a emitter/observer type problem. The former I'd solve in C 
with an object passed as a parameter that maintains state information 
whereas the latter registering callbacks for each of the states might be 
easier to work with.

It sounds like an asynchronous problem and callbacks tend to work well 
for them. You don't actually inform the caller though state variables 
but through calling the functions they've provided.


[toc] | [prev] | [next] | [standalone]


#29960

FromShao Miller <sha0.miller@gmail.com>
Date2013-01-11 15:23 -0500
Message-ID<kcpsbq$gaj$1@dont-email.me>
In reply to#29954
On 1/11/2013 14:22, Greg Martin wrote:
> On 13-01-11 10:56 AM, Shao Miller wrote:
>> On 1/11/2013 07:15, BartC wrote:
>>> "Shao Miller" <sha0.miller@gmail.com> wrote in message
>>> news:kco8gq$mao$1@dont-email.me...
>>>> On 1/10/2013 22:20, Ben Bacarisse wrote:
>>>
>>>>> Does this crop up for real?  I'd try to find a cleaner way to write
>>>>> the
>>>>> whole bar() + foo() interaction.
>>>
>>> That's the key I think (see below).
>>>
>>>> Sometimes 'bar' will have multiple characters to emit, and the caller
>>>> needs to call it multiple times to get all of the characters.  ("Here's
>>>> one translated character, but call me again because I have more.")
>>>>
>>>> Could be useful for escape sequences: "123${special}ABC" where the '$'
>>>> through until the 'l' wouldn't emit anything, but then the subsequent
>>>> '}'
>>>> would cause some special sequence to be emitted, where 'bar' would know
>>>> what to emit, but would have to be queried repeatedly until it finished
>>>> emitting the special sequence.
>>>
>>> At first glance this seems perfectly straightforward: bar is just called
>>> repeatedly until the 'EOF' marker you mention is returned. In this case,
>>> bar() returns the next character in the sequence, rather than some
>>> code. If
>>> the "123" in your example was consumed with no output, then bar wouldn't
>>> return until there was something to return, in this case the first
>>> character
>>> of whatever replaces "${special}".
>>>
>>> But it gets more complicated when you have to consider where this input
>>> string comes from. There might be some global state containing the input
>>> stream, the current position in that stream, and the current position in
>>> any
>>> translation string. Or that state might be contained inside bar().
>>>
>>> Or perhaps the caller might supply bar() with the next input character
>>> (and
>>> bar() needs some look-ahead to operate properly). Or a pointer to a
>>> struct
>>> containing the state (so that bar() can be called from different places,
>>> all
>>> with their own strings to translate).
>>>
>>>> So I thought it was a bit of an interesting challenge and I wonder what
>>>> strategies folks might've or might come up with, as a general pattern.
>>>
>>> It's not clear what the roles of bar() and foo() are. Maybe one of those
>>> returns the next translated character, but some more information is
>>> needed. The whole thing seems a bit like a tokeniser, or at least has
>>> some of the same problems to be solved.
>>>
>>
>> Yeah I was trying to abstract away the details and ask about a general
>> pattern (since that's what I'm interested in), but maybe the code
>> example was not illustrative enough. :)
>>
>> For the subsequent translation scenario I tried to describe, the caller
>> is responsible for getting a single input character 'ic'.  However they
>> do it should be opaque to the translating function, 'bar'.  The caller
>> calls 'bar' to translate 'ic' to '*oc'.
>>
>>    extern return_type bar(state_type state, char ic, char * oc);
>>
>> 'bar' might not emit any output character '*oc' if it's not yet ready.
>> In that case, the caller shouldn't work with '*oc'; shouldn't send it
>> wherever output is going.
>>
>> 'bar' might emit '*oc' and have nothing more to emit until processing
>> the next 'ic' or beyond.
>>
>> 'bar' might emit '*oc' and inform the caller that there are more output
>> characters pending, so the caller should call 'bar' again until they've
>> been consumed.  In this case, 'ic' is ignored for subsequent calls to
>> 'bar' as 'bar' already knows what sequence it wishes to emit based on
>> the 'ic' that triggered it.
>>
>> 'foo' was really just a place-holder for "something the caller does with
>> the results of 'bar'".  This might be to put the output characters in a
>> buffer or to send them to a stream.
>>
>> I'm interested in general C patterns for this kind of scenario without
>> getting too distracted by this particular example of "translating
>> characters".  Having said that, maybe working with this example scenario
>> is a better idea.
>>
>
> I found it a little difficult to grasp the initial scenario because of
> the magical occurrences going on in the functions. I think that to
> discuss patterns in any language the example needs to be have enough
> detail to represent the problem space. When I looked at your first post
> I thought you working on some strange sort of iterator but now it looks
> more like a emitter/observer type problem.

Sorry about that.

> The former I'd solve in C
> with an object passed as a parameter that maintains state information
> whereas the latter registering callbacks for each of the states might be
> easier to work with.
>
> It sounds like an asynchronous problem and callbacks tend to work well
> for them. You don't actually inform the caller though state variables
> but through calling the functions they've provided.
>

Right, callbacks were one of the possibilities mentioned upthread.  It 
does seem a bit like an asynchronous problem...  Maybe even possible to 
think of in terms of co-routines.  (But not in C.)

Do call-backs have a major advantage over some other strategy, such as 
repeated calls to the "emitter" and having the "observer" continue until 
observing an "end-of-sequence" value?  Or is it more a matter of 
individual preference, would you say?

Thanks for the feed-back!

-- 
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.

Cheerily,"  -- Richard Harter

[toc] | [prev] | [next] | [standalone]


#29965

FromGreg Martin <greg@softsprocket.com>
Date2013-01-11 13:09 -0800
Message-ID<ec%Hs.28287$Jq3.929@newsfe20.iad>
In reply to#29960
On 13-01-11 12:23 PM, Shao Miller wrote:
> On 1/11/2013 14:22, Greg Martin wrote:
>> On 13-01-11 10:56 AM, Shao Miller wrote:

>>
>> It sounds like an asynchronous problem and callbacks tend to work well
>> for them. You don't actually inform the caller though state variables
>> but through calling the functions they've provided.
>>
>
> Right, callbacks were one of the possibilities mentioned upthread.  It
> does seem a bit like an asynchronous problem...  Maybe even possible to
> think of in terms of co-routines.  (But not in C.)
>
> Do call-backs have a major advantage over some other strategy, such as
> repeated calls to the "emitter" and having the "observer" continue until
> observing an "end-of-sequence" value?  Or is it more a matter of
> individual preference, would you say?
> > Thanks for the feed-back!
>


It depends I think. If you have the means to say wait until something 
happens and when it does run the code suitable to the event while 
another part of your program does other work a callback makes sense. 
There's so many models for this. It depends on where it works to spend 
cycles and on timing of the data. If there's nothing for your program to 
do until foo() returns then blocking in it is fine. If you want to get 
back to foo quickly then a callback as an argument to a thread might be 
the answer.

e.g

void* poll_thread (void* args) {
	struct Callbacks* cb = (struct Callbacks*) args;
	struct DataAndState* it;

	while (it = foo()) {
	switch (it->type) {
		case this:
			cb->do_this (&it);
			break;
		case that:
			cb->do_that (&it);
			break;
		default:
	
			break;				
	}

	return args;
}

// or

/* args may need to be locked on access */
while (it = foo(&args)) {
	switch (it) {
		case this:
			fire_off_thread (&do_this, &args);
			break;
		case that:
			fire_off_thread (&do_that, &args);
			break;
		default:
			break;
	}
}

// or
...

[toc] | [prev] | [next] | [standalone]


#29969

From"BartC" <bc@freeuk.com>
Date2013-01-11 22:09 +0000
Message-ID<I40Is.23$sp6.20@fx02.fr7>
In reply to#29951
"Shao Miller" <sha0.miller@gmail.com> wrote in message
news:kcpn8m$gvs$1@dont-email.me...
> On 1/11/2013 07:15, BartC wrote:

>> It's not clear what the roles of bar() and foo() are. Maybe one of those
>> returns the next translated character, but some more information is
>> needed. The whole thing seems a bit like a tokeniser, or at least has
>> some of the same problems to be solved.

> For the subsequent translation scenario I tried to describe, the caller is
> responsible for getting a single input character 'ic'.  However they do it
> should be opaque to the translating function, 'bar'.  The caller calls
> 'bar' to translate 'ic' to '*oc'.
>
>   extern return_type bar(state_type state, char ic, char * oc);
>
> 'bar' might not emit any output character '*oc' if it's not yet ready. In
> that case, the caller shouldn't work with '*oc'; shouldn't send it
> wherever output is going.

Your function seems to be deceptively simple, but it's not! It could be
used, for example, to translate one language to another.

But suppose it is kept simple, so that all it does is translate N characters
of input (N>=1) to M characters of output (M>=0).

It might not know the value of N either, until it's read the N'th (or even
subsequent) character (for example, to map repeated characters to just one
or zero occurrences).

One problem I can see is that both N and M could be very large, for various 
reasons, but let's say the state variables can cope with buffering unlimited 
numbers of input and/or output characters.

Then we're pretty much back to the dialog in your original post. I don't
know if there's any standard way of doing these things.

I can tell you that I probably wouldn't stick with the character-at-time
model, but allow a string to be returned.

I think (not having tried) the states can be reduced to just two: (1) bar is
waiting for the character to start the next block of N; (2) it is waiting
for the character to delimit this block. With (2), bar() *has* to be called
again until this pattern is complete, and it reverts to state (1). (But it's
also possible some patterns will never complete, and the caller needs a way
of terminating.)

After each call there will also be some output in the form of a string
(which can also be done by a callback on each character), of any length
including zero.

-- 
bartc 

[toc] | [prev] | [next] | [standalone]


#30011

FromPaul N <gw7rib@aol.com>
Date2013-01-12 04:49 -0800
Message-ID<4325ab3f-8cf3-416f-98b1-2233b24d2728@t5g2000vba.googlegroups.com>
In reply to#29951
On Jan 11, 6:56 pm, Shao Miller <sha0.mil...@gmail.com> wrote:
> On 1/11/2013 07:15, BartC wrote:
>
>
>
>
>
> > "Shao Miller" <sha0.mil...@gmail.com> wrote in message
> >news:kco8gq$mao$1@dont-email.me...
> >> On 1/10/2013 22:20, Ben Bacarisse wrote:
>
> >>> Does this crop up for real?  I'd try to find a cleaner way to write the
> >>> whole bar() + foo() interaction.
>
> > That's the key I think (see below).
>
> >> Sometimes 'bar' will have multiple characters to emit, and the caller
> >> needs to call it multiple times to get all of the characters.  ("Here's
> >> one translated character, but call me again because I have more.")
>
> >> Could be useful for escape sequences: "123${special}ABC" where the '$'
> >> through until the 'l' wouldn't emit anything, but then the subsequent '}'
> >> would cause some special sequence to be emitted, where 'bar' would know
> >> what to emit, but would have to be queried repeatedly until it finished
> >> emitting the special sequence.
>
> > At first glance this seems perfectly straightforward: bar is just called
> > repeatedly until the 'EOF' marker you mention is returned. In this case,
> > bar() returns the next character in the sequence, rather than some code. If
> > the "123" in your example was consumed with no output, then bar wouldn't
> > return until there was something to return, in this case the first
> > character
> > of whatever replaces "${special}".
>
> > But it gets more complicated when you have to consider where this input
> > string comes from. There might be some global state containing the input
> > stream, the current position in that stream, and the current position in
> > any
> > translation string. Or that state might be contained inside bar().
>
> > Or perhaps the caller might supply bar() with the next input character (and
> > bar() needs some look-ahead to operate properly). Or a pointer to a struct
> > containing the state (so that bar() can be called from different places,
> > all
> > with their own strings to translate).
>
> >> So I thought it was a bit of an interesting challenge and I wonder what
> >> strategies folks might've or might come up with, as a general pattern.
>
> > It's not clear what the roles of bar() and foo() are. Maybe one of those
> > returns the next translated character, but some more information is
> > needed. The whole thing seems a bit like a tokeniser, or at least has
> > some of the same problems to be solved.
>
> Yeah I was trying to abstract away the details and ask about a general
> pattern (since that's what I'm interested in), but maybe the code
> example was not illustrative enough. :)
>
> For the subsequent translation scenario I tried to describe, the caller
> is responsible for getting a single input character 'ic'.  However they
> do it should be opaque to the translating function, 'bar'.  The caller
> calls 'bar' to translate 'ic' to '*oc'.
>
>    extern return_type bar(state_type state, char ic, char * oc);
>
> 'bar' might not emit any output character '*oc' if it's not yet ready.
> In that case, the caller shouldn't work with '*oc'; shouldn't send it
> wherever output is going.
>
> 'bar' might emit '*oc' and have nothing more to emit until processing
> the next 'ic' or beyond.
>
> 'bar' might emit '*oc' and inform the caller that there are more output
> characters pending, so the caller should call 'bar' again until they've
> been consumed.  In this case, 'ic' is ignored for subsequent calls to
> 'bar' as 'bar' already knows what sequence it wishes to emit based on
> the 'ic' that triggered it.
>
> 'foo' was really just a place-holder for "something the caller does with
> the results of 'bar'".  This might be to put the output characters in a
> buffer or to send them to a stream.
>
> I'm interested in general C patterns for this kind of scenario without
> getting too distracted by this particular example of "translating
> characters".  Having said that, maybe working with this example scenario
> is a better idea.

What you're doing seems much the same as what a compiler does, so you
could read up on how they do it. I think this stage is called lexical.

I'd be inclined to drop the whole idea of sending characters to your
function. Make the function return the next output character, or EOF
if it is actually the end of the input file, and leave the function to
read in as many characters as it needs to get an output character.
(This may be what you are getting at by talking about callbacks, but
there's no need to use a callback as such if there is only one other
function producing the input characters.) In short, write a function
that you can pull characters from, and which will in turn pull in the
characters it needs, instead of trying to push characters into the
function.

[toc] | [prev] | [next] | [standalone]


#30096

FromShao Miller <sha0.miller@gmail.com>
Date2013-01-13 20:30 -0500
Message-ID<kcvn37$n4b$1@dont-email.me>
In reply to#30011
On 1/12/2013 07:49, Paul N wrote:
>
> What you're doing seems much the same as what a compiler does, so you
> could read up on how they do it. I think this stage is called lexical.
>
> I'd be inclined to drop the whole idea of sending characters to your
> function. Make the function return the next output character, or EOF
> if it is actually the end of the input file, and leave the function to
> read in as many characters as it needs to get an output character.
> (This may be what you are getting at by talking about callbacks, but
> there's no need to use a callback as such if there is only one other
> function producing the input characters.) In short, write a function
> that you can pull characters from, and which will in turn pull in the
> characters it needs, instead of trying to push characters into the
> function.
>

Thank you for the feed-back.

Yes indeed, the idea was that the 'bar' function knows how to translate, 
and so is fed input characters, but their source is opaque to 'bar'. 
The caller might provide input characters from a buffer, or might read 
them from a stream, or who-knows-how-else.

And what to do with the output characters should also be opaque to 
'bar'; it just translates.

The idea of passing one or more callbacks could certainly work, instead. 
  For example:

   enum e_callback_result {
       cv_yield,
       cv_break,
       cv_more
     };

   typedef enum e_callback_result f_callback(void *);

   void translate(
       void * context,
       f_callback * next_input,
       f_callback * next_output
     ) {
       enum e_callback_result rv;

       rv = cv_more;
       while (rv != cv_break) {
           while ((rv = next_input(context)) == cv_more)
             continue;

           if (rv == cv_break)
             break;

           while ((rv = next_output(context)) == cv_more)
             continue;
         }
     }

Where the input fetching could yield after each input character, but the 
output function might deliberately spin for a while.  This is more 
symmetrical than the "caller versus 'bar'" style.  Is that worth 
something, do you think?  Or was it not quite the "pull in the character 
it needs" that you had in mind?

-- 
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.

Cheerily,"  -- Richard Harter

[toc] | [prev] | [next] | [standalone]


#29964

Fromglen herrmannsfeldt <gah@ugcs.caltech.edu>
Date2013-01-11 21:02 +0000
Message-ID<kcpul2$69j$1@speranza.aioe.org>
In reply to#29917
Shao Miller <sha0.miller@gmail.com> wrote:

> Suppose you have a function 'bar' that returns a value that means one of:
>   - Do 'foo' zero times
>   - Do 'foo' one time
>   - Do 'foo' more than one time
 
> What's your favourite way of handling such a value?  

It isn't very C-like to do it that way.

Since C doesn't allow multiple entry points to a function
(like Fortran or PL/I ENTRY statement) it is usual to have one function
do both jobs.

Note, for example, the C strtok() function.

With strtok, on the first call you pass the string to tokenize,
on subsequent calls you pass NULL. (It does keep state in static
storage, and so can't be used in reentrant code.)

In the zero case, strtok() returns NULL on the first call,
for the one time case, NULL on the second call, and more than
one, on the N+1th call. 

So, why do you special case the 0 and 1 case? 

If you really need that, loop through counting the number of
times the function returns non-NULL, then start over with
the appropriate choice. 

Also, note for example, the Java Iterator class.

-- glen

[toc] | [prev] | [next] | [standalone]


#30072

FromPhil Carmody <thefatphil_demunged@yahoo.co.uk>
Date2013-01-13 20:28 +0200
Message-ID<87ehhpkkd7.fsf@bazspaz.fatphil.org>
In reply to#29917
Shao Miller <sha0.miller@gmail.com> writes:

> Suppose you have a function 'bar' that returns a value that means one of:
>    - Do 'foo' zero times
>    - Do 'foo' one time
>    - Do 'foo' more than one time
> 
> What's your favourite way of handling such a value?  For example:
> 
>    while ((more = bar()) != cv_zero_times) {
>        /* Do it at least once */
>        foo();
> 
>        /* Do it more than once? */
>        if (more != cv_more_times)
>          break;
>      }

Vomit. Doesn't even satisfy your initial description either (which
makes no mention of calling 'bar' multiple times).

From what you've actually described, I'd do:

int count=bar(); /* 0, 1, or more */
while(count) {
  foo();
  count -= (count&1); /* never drops below 2 */
}

Phil
-- 
I'm not saying that google groups censors my posts, but there's a strong link
between me saying "google groups sucks" in articles, and them disappearing.

Oh - I guess I might be saying that google groups censors my posts.

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.c


csiph-web