Re: Dreaming of new generation IDE
I can't believe the code editing situation today is in a such sorry state. I can't believe an old coder is feeling so sorry for himself. Today, I tried to understand the twisted.web.client code and I found 3 methods I couldn't find by who were called. I asked on the mailing list and they suggested me where they were called and that the tool for such thing is grep. So, you grep, you get a list of files, you open each one of them and keep scrolling and switching from one file to another... endlessly. Maybe I'm getting old, but I tend to get lost in the process. Maybe the relevant lesson to be taken from Smalltalk is *not* put it all in one image but instead write code to solve problems, e.g., reading code I suggest defining a few shell functions to *automate* the search, for example in zsh function allf () { # Recursively find files with suffix matching comma-separated list in $1. # For example, allf cpp,hpp finds all *.cpp and *.hpp. find . -type f | grep -E \.(${1//,/|})$ } function src () { # Similar to allf, then search for a regex among the results. find . -type f -print0 | grep -zE \.(${1//,/|})$ | xargs -0 grep - lE $2 } function srcl () { # Similar to src (see above), # then search for a pattern among the results, # and pass matching files to less. src $1 $2 | xargs less -p $2 } Smalltalk's images are cool. But they are such a huge hammer, and they impose so many additional requirements! The costs outweigh the cool. -- FC -- http://mail.python.org/mailman/listinfo/python-list
Re: python bijection
[In re R. Hettinger's critiques] * it extends the language with arcane syntax tricks... I think most of these in the current version of J. Bronson's bidict can be left unused, or removed altogether. In almost all cases, a bidict should be accessed as an ordinary python dict. * we've already got one (actually two). The two dictionary approach... Solutions such as bidict just automate the two-dict approach. ...sqlite3 provides another way... In many many cases, using a dB (even a lightweight such as sqlite3) is swatting the fly with a sledgehammer :-) Since bijections are symmetrical, they do not have an obvious direction (which is the primary key, the husband or the wife?). I think this is easy to solve with a classmethod constructor that produces a pair of linked dicts. For example, husband2wife, wife2husband = bidict.makepair(('Fred', 'John'), ('Mary', 'Ruth')) Obviously from the code this pair of bidicts are linked, and the direction of each mapping is obvious from its name. Metaprogramming idioms like namedtuple are not required. * the semantics of a bijection aren't obvious: b['x'] = 'ex' # first record: ('x', 'ex') b['y'] = 'why' # second record: ('y', 'why') b[:'why'] = 'x' # do two records collapse into one? # is there an error? Among the various critiques, I think this is the most significant. When I was fiddling with my implementation, I was disturbed that the code bidict[newKey] = oldValue should have the subtle side-effect del bidict.inv[oldValue] And there is a much stranger case. Suppose bidict[key1]=val1 and bidict[key2]=val2. Then the code bidict[key1] = val2 should have the extremely subtle side-effects del bidict[key2] # because val2 has been re-mapped del bidict.inv[val1] # because key1 has been re-mapped Blech! I think there must be something better. It would be interesting to hear more opinions on the matter. I propose raising ValueError when operating on one key would also silently re-map or delete a different (key,value) pair. This would disallow both of the above cases. To get the effect of the first case, one would simply operate on the inverse mapping: bidict.inv[oldValue] = newKey This should not be confusing: it's exactly how a python dict would operate, except the linked mapping is altered to match, which is the bookkeeping we want to automate in the first place. To get the effect of the second case, one would have to explicitly demand the side- effects: del bidict[key2] del bidict.inv[val1] bidict[key1] = val2 Also not confusing. -- FC -- http://mail.python.org/mailman/listinfo/python-list
Re: python bijection
I was really inspired by this discussion thread! :-) After much tinkering, I think I have a simpler solution. Just make the inverse mapping accessible via an attribute, -AND- bind the inverse of -THAT- mapping back to the original. The result is a python dict with NO NEW METHODS except this inverse-mapping attribute. I have posted it on code.activestate.com as a href=http://code.activestate.com/recipes/576968/;Recipe 576968: Flipdict -- python dict that also maintains a one-to-one inverse mapping/a -- F. Carr -- http://mail.python.org/mailman/listinfo/python-list
Re: Most efficient way to pre-grow a list?
Hmmm. I am trying some algorithms, and timeit reports that a list.extend variant is fastest... WTH?! Really this seems like it must be a bug in implementing the [None]*x idiom. As expected, appending one-at-a-time is slowest (by an order of magnitude): % python -m timeit -s N=100 \ z=[2**32-1] \ while len(z)N: z.append(z[0]) 10 loops, best of 3: 223 msec per loop A method based on list.extend doubling is much better: % python -m timeit -s N=100 \ z=[2**32-1] \ while len(z)N: z.extend(z[:N-len(z)]) 10 loops, best of 3: 22.2 msec per loop The straightforward pythonic solution is better yet: % python -m timeit -s N=100 \ z=[2**32-1]*N 100 loops, best of 3: 8.81 msec per loop And the winner for speed is... over-allocate using list.extend, then delete! % python -m timeit -s N=100 \ z=[2**32-1] \ while len(z)N: z.extend(z) \ del z[N:] 100 loops, best of 3: 6.93 msec per loop Using array.array('I') gives similar results: % python -m timeit -s import array -s N=100 \ z=array.array('I', [2**32-1]) \ while len(z)N: z.append(z[0]) 10 loops, best of 3: 278 msec per loop % python -m timeit -s import array -s N=100 \ z=array.array('I', [2**32-1]) \ while len(z)N: z.extend(z[:N-len(z)]) 100 loops, best of 3: 7.82 msec per loop % python -m timeit -s import array -s N=100 \ z=array.array('I', [2**32-1]) \ z=z*N 100 loops, best of 3: 6.04 msec per loop % python -m timeit -s import array -s N=100 \ z=array.array('I', [2**32-1]) \ while len(z)N: z.extend(z) \ del z[N:] 100 loops, best of 3: 4.02 msec per loop These results appear to scale up. I replaced N=100 2**20 with N=2**25 and obtained the same relative ordering: % python -m timeit -s N=2**25 \ z=[2**32-1] \ while len(z)N: z.append(z[0]) [Ctrl-C after a lng wait] % python -m timeit -s N=2**25 \ z=[2**32-1] \ while len(z)N: z.extend(z[:N-len(z)]) 10 loops, best of 3: 872 msec per loop % python -m timeit -s N=2**25 \ z=[2**32-1]*N 10 loops, best of 3: 434 msec per loop % python -m timeit -s N=2**25 \ z=[2**32-1] \ while len(z)N: z.extend(z) \ del z[N:] 10 loops, best of 3: 346 msec per loop And just to see if array.array can help us when large amounts of memory are in use: % python -m timeit -s import array -s N=2**25 \ z=array.array('I', [2**32-1]) \ while len(z)N: z.extend(z) \ del z[N:] 10 loops, best of 3: 149 msec per loop If speed is the overriding concern, then there's another factor of two right there. Python version and hardware info: Python 2.6.2 (release26-maint, Apr 19 2009, 01:58:18) [GCC 4.3.3] on linux2 12Gb RAM on a quad-core Intel Xeon 3Ghz CPU -- FC -- http://mail.python.org/mailman/listinfo/python-list
Re: Doubley imported module caused devastating bug
I would like to propose that it be made impossible in the Python source to import two instances of the same module. A fully-automatic solution is more difficult than it might seem at first: http://www.python.org/dev/peps/pep-0328/ But there is a simple code-discipline solution: never ever use relative imports, even between code in the same package. We got bit by double-imports (a mix of relative, absolute, and even cross-imports A import B and B import A) early on in one of our projects. The symptom was that the imported module would be initialized *twice*, once for a relative import and once for an absolute. This is not a happy situation for pseudo-singletons like the logging module --- esp. if one is hacking the internals! :-) We no longer use relative imports *EVER*, even within the same package. Perhaps Perforce is doing something tricky with scoping or importing, and you've just managed to stumble across this trickiness because of a double-import. Good luck, these things are a bugger to debug. -- http://mail.python.org/mailman/listinfo/python-list
Re: itertools.intersect?
On Jun 11, 6:23 pm, Mensanator mensana...@aol.com wrote: Removing the duplicates could be a big problem. It is fairly easy to ignore duplicates in a sorted list: pre from itertools import groupby def unique(ordered): Yield the unique elements from a sorted iterable. for key,_ in groupby(ordered): yield key /pre Combining this with some ideas of others, we have a simple, complete solution: pre def intersect(*ascendingSeqs): Yield the intersection of zero or more ascending iterables. N=len(ascendingSeqs) if N==0: return unq = [unique(s) for s in ascendingSeqs] val = [u.next() for u in unq] while True: for i in range(N): while val[i-1] val[i]: val[i] = unq[i].next() if val[0]==val[-1]: yield val[0] val[-1] = unq[-1].next() /pre This works with empty arg-lists; combinations of empty, infinite and finite iterators; iterators with duplicate elements; etc. The only requirement is that all iterators are sorted ascending. -- FC -- http://mail.python.org/mailman/listinfo/python-list
Re: Self function
Scheme is arguably the programming language with the most support for recursion, including the most complete support for tail-call optimization, constructs like letrec to define collections of multiply-recursive functions (which get used very frequently -- by no means is it an uncommon situation, as you suggest in your initial post), and hardly any iterative loops. Yet -- scheme does not provide out-of-the-box support for your proposed let-a-function-implicitly- refer-to-itself idea. This suggests that the idea itself runs counter to more important aspects of a programming language. In the special case of a self-recursive function, you would like re- naming to just work. Out of morbid curiosity, I am compelled to ask... why do you expect that re-naming anything --- a function, a class, a module, a variable, anything --- in just one place but not all the others should ever, under any circumstances, just work ? -- http://mail.python.org/mailman/listinfo/python-list