[Tim on comparing fringes of two trees]: > In Icon you need to create co-expressions to solve this > problem, because its generators aren't explicitly resumable, > and Icon has no way to spell "kick a pair of generators in > lockstep". But explicitly resumable generators are in fact > "good enough" for this classic example, which is usually used > to motivate coroutines. Apparently they are good for lots of other things too. Tonight I implemented passing values using resume(). Next, I decided to see if I had enough magic juice to tackle the coroutine example from Gordon's stackless tutorial. Its turns out that I didn't need the extra functionality. Generators are enough. The code is not too long so I've attached it. I figure that some people might need a break from 2.1 release issues. I think the generator version is even simpler than the coroutine version. Neil # Generator example: # The program is a variation of a Simula 67 program due to Dahl & Hoare, # who in turn credit the original example to Conway. # # We have a number of input lines, terminated by a 0 byte. The problem # is to squash them together into output lines containing 72 characters # each. A semicolon must be added between input lines. Runs of blanks # and tabs in input lines must be squashed into single blanks. # Occurrences of "**" in input lines must be replaced by "^". # # Here's a test case: test = """\ d = sqrt(b**2 - 4*a*c) twoa = 2*a L = -b/twoa R = d/twoa A1 = L + R A2 = L - R\0 """ # The program should print: # d = sqrt(b^2 - 4*a*c);twoa = 2*a; L = -b/twoa; R = d/twoa; A1 = L + R; #A2 = L - R #done # getlines: delivers the input lines # disassemble: takes input line and delivers them one # character at a time, also inserting a semicolon into # the stream between lines # squasher: takes characters and passes them on, first replacing # "**" with "^" and squashing runs of whitespace # assembler: takes characters and packs them into lines with 72 # character each; when it sees a null byte, passes the last # line to putline and then kills all the coroutines from Generator import Generator def getlines(text): g = Generator() for line in text.split('\n'): g.suspend(line) g.end() def disassemble(cards): g = Generator() try: for card in cards: for i in range(len(card)): if card[i] == '\0': raise EOFError g.suspend(card[i]) g.suspend(';') except EOFError: pass while 1: g.suspend('') # infinite stream, handy for squash() def squash(chars): g = Generator() while 1: c = chars.next() if not c: break if c == '*': c2 = chars.next() if c2 == '*': c = '^' else: g.suspend(c) c = c2 if c in ' \t': while 1: c2 = chars.next() if c2 not in ' \t': break g.suspend(' ') c = c2 if c == '\0': g.end() g.suspend(c) g.end() def assemble(chars): g = Generator() line = '' for c in chars: if c == '\0': g.end() if len(line) == 72: g.suspend(line) line = '' line = line + c line = line + ' '*(72 - len(line)) g.suspend(line) g.end() if __name__ == '__main__': for line in assemble(squash(disassemble(getlines(test)))): print line print 'done'
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4