![]() |
Favourite Pattern for Processing Zero, Once, Multiple
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 |
Re: Favourite Pattern for Processing Zero, Once, Multiple
"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 |
Re: Favourite Pattern for Processing Zero, Once, Multiple
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 |
Re: Favourite Pattern for Processing Zero, Once, Multiple
"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 |
Re: Favourite Pattern for Processing Zero, Once, Multiple
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. |
Re: Favourite Pattern for Processing Zero, Once, Multiple
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 |
Re: Favourite Pattern for Processing Zero, Once, Multiple
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 |
Re: Favourite Pattern for Processing Zero, Once, Multiple
"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 |
Re: Favourite Pattern for Processing Zero, Once, Multiple
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 |
Re: Favourite Pattern for Processing Zero, Once, Multiple
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 |
| All times are GMT. The time now is 10:20 PM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.