RE: [Python-Dev] PEP 327: Decimal Data Type
I wrote:
(a) What's the syntax for changing the context? I'd think we'd want a "pushDecimalContext()" and "popDecimalContext()" sort of approach, since most well-behaved routines will want to restore their caller's context.
Facundo Batista replies:
You can save a copy of the context in a variable and then restore it. No stack.
Imagine the following senario. I write some code which uses Decimal, and which sets the context to get the desired rounding behavior. Somewhere in my code I call a routine written by somebody else... perhaps some library code... which also does some calculations using Decimal. It would be a major pain if every time I called that library code it changed the context. I'd have to keep setting the context back after each and every call to the library code. A well-behaved library will not require me to go through these contortions, so after it does its work it will set the context back to what it was when I called it. It seems to me that in almost all situations where one changes the context, one will also want to restore it later. If so, then it seems perverse to tell every user that they must capture and store the old context someplace and restore it later. Why not make the best practice be the *obvious* idiom by providing matched pushContext() and popContext() functions as the normal way of setting the context. Of course, one could choose to call pushContext() without a matching popContext(), or call popContext() repeatedly until the stack is empty (some exception is raised), but if the best behavior is the easy behavior then most people will use it. And if that didn't convince you, then go ahead... I think it's only a minor detail. -- Michael Chermside
[Michael Chermside]
Imagine the following senario. I write some code which uses Decimal, and which sets the context to get the desired rounding behavior. Somewhere in my code I call a routine written by somebody else... perhaps some library code... which also does some calculations using Decimal.
It would be a major pain if every time I called that library code it changed the context. I'd have to keep setting the context back after each and every call to the library code. A well-behaved library will not require me to go through these contortions, so after it does its work it will set the context back to what it was when I called it.
A well-designed library will restore only *part* of the context. Some of the state in numeric context controls arithmetic behavior, but other parts are informational, telling you about exceptional conditions that occurred. The user can choose to let exceptions be raised, or to suppress them (via settings in numeric context). In the latter case, knowledge that an exceptional condition occurred is *recorded* in context. A well-designed library can't assume that the user wants exceptions to be raised, but must inform a user running in "non-stop" mode that exceptional conditions occurred. Context is the way to do that; context holds both input and output state. It's difficult to write high-quality numeric libraries. The facilities offered by numeric context are a great aid in doing so, but it's still too complex for simple gimmicks like "a stack" to help. The burden is on code that changes context to do so correctly from its caller's POV; if you call a routine that makes a mess of your context, that's an error in the routine you called. In the same vein, if you write a routine that requires a specific rounding mode, and don't arrange to force that rounding mode for the duration of your routine, your routine is in error. It's also in error if it doesn't restore the rounding mode in effect when it was entered. It's also probably in error if it *does* blindly restore the settings of the informational flags.
Tim Peters <tim.one@comcast.net>:
A well-designed library will restore only *part* of the context. Some of the state in numeric context controls arithmetic behavior, but other parts are informational, telling you about exceptional conditions that occurred.
That suggests there shouldn't be a single context object, but two separate objects, one for modes and one for exception flags. The modes object could then be saved and restored without affecting the flags. Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+
[Greg Ewing]
That suggests there shouldn't be a single context object, but two separate objects, one for modes and one for exception flags. The modes object could then be saved and restored without affecting the flags.
Possibly. I'm more interested to see us adhere as closely as possible to the relevant standards at the start; there's plenty to be done without piling on speculative "convenience features": http://www2.hursley.ibm.com/decimal/
On Mon, 2 Feb 2004, Michael Chermside wrote:
It would be a major pain if every time I called that library code it changed the context.
That would be badly behaved library code. One thing that might be an issue is that context stacks tend to be real headaches in threaded code. The context stack must unwind in the "pushed" order even though the "completion" order may be very different. Such a stack would make the ordering of calls to the Decimal module subject to strange errors. Another thing that might come up is that a context could be a microprocessor resource. Fully restoring such a resource can often be very expensive and may not even be possible. -a
participants (4)
-
Andrew P. Lentvorski, Jr.
-
Greg Ewing
-
Michael Chermside
-
Tim Peters