Programmers like to talk about how concurrency (multithreading, etc.) makes code more complicated. And sometimes that’s true. But there are a few areas where concurrency actually makes things simpler; the “samefringe problem” is one classic example, but the “telegram problem” is another one.
The “telegram problem” is to refill paragraphs, so as many words as possible fit on each line, like the Unix command `fmt`. Here are solutions with and without using Python’s built-in “generator” form of concurrency. #!/usr/bin/python "Telegram problem, aka fmt." import sys words = lambda line: line.split() width = lambda buf: sum(len(word) for word in buf) + len(buf) - 1 def telegram_generator_1(infile, maxwidth): """A purely procedural version that doesn't use generators internally. This is what you get if you're writing a conventional procedural program to solve the problem by imperatively producing output lines. """ buf = [] for line in infile: buf.extend(words(line)) while width(buf) > maxwidth: n = len(buf) while width(buf[:n]) > maxwidth: n -= 1 yield ' '.join(buf[:n]) buf[:n] = [] yield ' '.join(buf) # XXX what to do if a word is wider than the line? def telegram_super_cool(infile, maxwidth): """Here's a totally generator-oriented version.""" buf = [] for word in (word for line in lines for word in words(line)): buf.append(word) if width(buf) > maxwidth: yield ' '.join(buf[:-1]) buf[:-1] = [] yield ' '.join(buf) class IteratorBase: def __iter__(self): return self class telegram_super_cool_explicit_cps(IteratorBase): """Here's an explicit iterator implementation. I wrote this from telegram_super_cool above, twiddling it a little to reduce excess complexity. It's remarkable how much excess complexity still remains. """ def __init__(self, infile, maxwidth): self.infile, self.maxwidth = iter(infile), maxwidth self.buf = [] self.done = False self.buf2 = [] def next_word(self): while not self.buf2: self.buf2 = words(self.infile.next()) return self.buf2.pop(0) def next(self): if self.done: raise StopIteration while True: try: self.buf.append(self.next_word()) except StopIteration: self.done = True return ' '.join(self.buf) if width(self.buf) > self.maxwidth: rv = ' '.join(self.buf[:-1]) self.buf[:-1] = [] return rv if __name__ == '__main__': for line in telegram_super_cool_explicit_cps(sys.stdin, 72): print line # Like everything else posted to kragen-hacks without a notice to the # contrary, this software is in the public domain. -- To unsubscribe: http://lists.canonical.org/mailman/listinfo/kragen-hacks