Function Hash: Check it in?
Attached is an example Python session after I patched the intepreter. The test-suite passes all right. I want an OK to check this in. Here is the patch: Index: Objects/funcobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/funcobject.c,v retrieving revision 2.33 diff -c -r2.33 funcobject.c *** Objects/funcobject.c 2001/01/25 20:06:59 2.33 --- Objects/funcobject.c 2001/01/27 19:13:08 *************** *** 347,358 **** 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ ! (cmpfunc)func_compare, /*tp_compare*/ (reprfunc)func_repr, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ ! (hashfunc)func_hash, /*tp_hash*/ 0, /*tp_call*/ 0, /*tp_str*/ (getattrofunc)func_getattro, /*tp_getattro*/ --- 347,358 ---- 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ ! 0, /*tp_compare*/ (reprfunc)func_repr, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ ! 0, /*tp_hash*/ 0, /*tp_call*/ 0, /*tp_str*/ (getattrofunc)func_getattro, /*tp_getattro*/ Python 2.1a1 (#1, Jan 27 2001, 21:01:24) [GCC 2.95.3 20010111 (prerelease)] on linux2 Type "copyright", "credits" or "license" for more information.
def foo(): ... pass ... def bar(): ... pass ... hash(foo) 135484636 hash(bar) 135481676 foo == bar 0 d = {} d[foo] =1 def temp(): ... print "baz" ... foo.func_code = temp.func_code d[foo] 1
-- Moshe Zadka <sig@zadka.site.co.il> This is a signature anti-virus. Please stop the spread of signature viruses! Fingerprint: 4BD1 7705 EEC0 260A 7F21 4817 C7FC A636 46D0 1BD6
"MZ" == Moshe Zadka <moshez@zadka.site.co.il> writes:
MZ> Attached is an example Python session after I patched the MZ> intepreter. The test-suite passes all right. MZ> I want an OK to check this in. Moshe, please remove the func_hash() and func_compare() functions, and if the patch passes the test suite, go ahead and check it all in. Please also check in a test case. Thanks, -Barry
On Mon, 29 Jan 2001 00:04:12 -0500, barry@digicool.com (Barry A. Warsaw) wrote:
Oh yeah, please also add an entry to the NEWS file.
Done. The checkin to the NEWS file will be done in about a million years, when my antique of a modem finishes sending the data. I had to change test_opcodes since it tested that functions with the same code compare equal. -- Moshe Zadka <sig@zadka.site.co.il> This is a signature anti-virus. Please stop the spread of signature viruses! Fingerprint: 4BD1 7705 EEC0 260A 7F21 4817 C7FC A636 46D0 1BD6
On Mon, 29 Jan 2001 08:26:25 +0200 (IST), you wrote:
I had to change test_opcodes since it tested that functions with the same code compare equal.
Thanks. With this change, Jython too can complete the test_opcodes. In Jython a code object can never compare equal to anything but itself. regards, finn
On Mon, 29 Jan 2001 13:48:44 GMT, bckfnn@worldonline.dk (Finn Bock) wrote:
Thanks. With this change, Jython too can complete the test_opcodes. In Jython a code object can never compare equal to anything but itself.
Great! I'm happy to have helped. I'm starting to wonder what the tests really test: the language definition, or accidents of the implementation? -- Moshe Zadka <sig@zadka.site.co.il> This is a signature anti-virus. Please stop the spread of signature viruses! Fingerprint: 4BD1 7705 EEC0 260A 7F21 4817 C7FC A636 46D0 1BD6
I'm starting to wonder what the tests really test: the language definition, or accidents of the implementation?
It's good to test conformance to the language definition, but this is also a regression test for the implementation. The "accidents of the implementation" definitely need to be tested. E.g. if we decide that repr(s) uses \n rather than \012 or \x0a, this should be tested too. The language definition gives the implementer a choice here; but once the implementer has made a choice, it's good to have a test that tests that this choice is implemented correctly. Perhaps there should be several parts to the regression test, e.g. language conformance, library conformance, platform-specific features, and implementation conformance? --Guido van Rossum (home page: http://www.python.org/~guido/)
On Mon, 29 Jan 2001 10:30:17 -0500, Guido van Rossum <guido@digicool.com> wrote:
It's good to test conformance to the language definition, but this is also a regression test for the implementation. The "accidents of the implementation" definitely need to be tested. E.g. if we decide that repr(s) uses \n rather than \012 or \x0a, this should be tested too. The language definition gives the implementer a choice here; but once the implementer has made a choice, it's good to have a test that tests that this choice is implemented correctly.
I agree.
Perhaps there should be several parts to the regression test, e.g. language conformance, library conformance, platform-specific features, and implementation conformance?
This sounds like a good idea...probably for the 2.2 timeline. -- Moshe Zadka <sig@zadka.site.co.il> This is a signature anti-virus. Please stop the spread of signature viruses! Fingerprint: 4BD1 7705 EEC0 260A 7F21 4817 C7FC A636 46D0 1BD6
On Mon, 29 Jan 2001 16:04:47 +0200 (IST), you wrote:
On Mon, 29 Jan 2001 13:48:44 GMT, bckfnn@worldonline.dk (Finn Bock) wrote:
Thanks. With this change, Jython too can complete the test_opcodes. In Jython a code object can never compare equal to anything but itself.
Great! I'm happy to have helped. I'm starting to wonder what the tests really test: the language definition, or accidents of the implementation?
Based on the amount of code in test_opcodes dedicated to code comparison, I doubt this particular situation was an accident. The problems I have had with the test suite are better described as accidents of the tests themself. From test_extcall: We expected (repr): "g() got multiple values for keyword argument 'b'" But instead we got: "g() got multiple values for keyword argument 'a'" This is caused by a difference in iteration over a dictionary. Or from test_import: test test_import crashed -- java.lang.ClassFormatError: java.lang.ClassFormatError: @test$py (Illegal Class name "@test$py") where '@' isn't allowed in java classnames. These are failures that have very little to do with the thing the test are about and nothing at all to do with the language definition. regards, finn
[Moshe Zadka]
... I'm starting to wonder what the tests really test: the language definition, or accidents of the implementation?
You'd be amazed (appalled?) at how hard it is to separate them. In two previous lives as a Big Iron compiler hacker, we routinely had to get our compilers validated by a govt agency before any US govt account would be allowed to buy our stuff; e.g., http://www.itl.nist.gov/div897/ctg/vpl/language.htm This usually *started* as a two-day process, flying the inspector to our headquarters, taking perhaps 2 minutes of machine time to run the test suite, then sitting around that day and into the next arguing about whether the "failures" were due to non-standard assumptions in the tests, or compiler bugs. It was almost always the former, but sometimes that didn't get fully resolved for months (if the inspector was being particularly troublesome, it could require getting an Official Interpretation from the relevant stds body -- not swift!). (BTW, this is one reason huge customers are often very reluctant to move to a new release: the validation process can be very expensive and drag on for months)
def f(): ... global g ... g += 1 ... return g ... g = 0 d = {f(): f()} d {2: 1}
The Python Lang Ref doesn't really say whether {2: 1} or {1: 2} "should be" the result, nor does it say it's implementation-defined. If you *asked* Guido what he thought it should do, he'd probably say {1: 2} (not much of a guess: I asked him in the past, and that's what he did say <wink>). Something "like that" can show up in the test suite, but buried under layers of obfuscating accidents. Nobody is likely to realize it in the absence of a failure motivating people to search for it. Which is a trap: sometimes ours was the only compiler (of dozens and dozens) that had *ever* "failed" a particular test. This was most often the case at Cray Research, which had bizarre (but exceedingly fast -- which is what Cray's customers valued most) floating-point arithmetic. I recall one test in particular that failed because Cray's was the only box on earth that set I to 1 in INTEGER I I = 6.0/3.0 Fortran doesn't define that the result must be 2. But-- you guessed it --neither does Python. Cute: at KSR, INT(6.0/3.0) did return 2 -- but INT(98./49.) did not <wink>. then-again-the-python-test-suite-is-still-shallow-ly y'rs - tim
tim says:
Cray's was the only box on earth that set I to 1 in
INTEGER I I = 6.0/3.0
Fortran doesn't define that the result must be 2. But-- you guessed it --neither does Python.
I would _guess_ that the IEEE 754 floating point standard does require that, but I haven't actually gotten my hands on a copy of the standard yet. If it doesn't, I may have to stop writing code that depends on the assumption that floating point computation is exact for exactly representable integers. If so, then we're reasonably safe; there aren't many non-IEEE machines left these days. Un-lurking-ly yours, Paul Hughett
[Paul Hughett]
I would _guess_ that the IEEE 754 floating point standard does require that [6./3. == 2.],
It does, but 754 is silent on how languages may or may not *bind* to its semantics. The C99 std finally addresses that (15 years after 754), and Java does too (albeit in a way Kahan despises), but that's about it for "name brand" <wink> languages.
... If it doesn't, I may have to stop writing code that depends on the assumption that floating point computation is exact for exactly representable integers. If so, then we're reasonably safe; there aren't many non-IEEE machines left these days.
I'm afraid you've got no guarantees even on a box with 100% conforming 754 hardware. One of the last "mystery bugs" I helped tracked down at my previous employer only showed up under Intel's C++ compiler. It turned out the compiler was looking for code of the form: double *a, *b, scale; for (i=0; i < n; ++i) { a[i] = b[i] / scale; } and rewriting it as: double __temp = 1./scale; for (i=0; i < n; ++i) { a[i] = b[i] * __temp; } for speed. As time goes on, PC compilers are becoming more and more like Cray's and KSR's in this respect: float division is much more expensive than float mult, and so variations of "so multiply by the reciprocal instead" are hard for vendors to resist. And, e.g., under 754 double rules, (17. * 123.) * (1./123.) must *not* yield exactly 17.0 if done wholly in 754 double (but then 754 says nothing about how any language maps that string to 754 operations). if-you-like-logic-chopping-you'll-love-arguing-stds<wink>-ly y'rs - tim
participants (6)
-
barry@digicool.com -
bckfnn@worldonline.dk -
Guido van Rossum -
Moshe Zadka -
Paul Hughett -
Tim Peters