Comparisons and sorting of a numeric class....

Rustom Mody rustompmody at gmail.com
Fri Jan 23 16:31:29 CET 2015


On Friday, January 23, 2015 at 5:18:32 PM UTC+5:30, Andrew Robinson wrote:
> On 01/15/2015 09:05 AM, Ian Kelly wrote:
> > On Thu, Jan 15, 2015 at 12:23 AM, Andrew Robinson wrote:
> >> Can you name any other language that *does* allow subclassing of
> >> booleans or creation of new boolean values?
> >>
> >> Yes. Several off the top of my head -- and I have mentioned these before.
> >> They generally come with the extra subclasses pre-created and the user
> >> doesn't get to create the classes, but only use them; none the less -- they
> >> have more than two values with which to do logic equations with.
> >>
> >> VHDL, Verilog, HDL, Silos III, and there are IEEE variants also.
> >> C/C++ historically allowed you to do it with instances included, although I
> >> am not sure it still does.
> > Sorry, let me rehprase my question. Of course there will be
> > special-purpose languages that allow you to do interesting things with
> > the logic values and operators. Can you name any other
> > *general-purpose* language that allows subclassing of booleans or
> > creation of new boolean values? If not, it seems rather unfair to
> > single out Python and marvel that this isn't allowed when it's
> > actually quite normal to disallow it. Unless you care to provide an
> > example, I am fairly sure your claim of C/C++ is wrong. The bool type
> > in C++ is a primitive type, none of which can be inherited from. C
> > doesn't even have a bool type; at most you have macros for true and
> > false to 1 and 0, so the "booleans" there are just ordinary integers.
> Ian,
> I agree with you mostly; there is good reason to pick on other 
> languages, too, with respect to what a bool is.
> 
> Although, I have to laugh -- Verilog can syntheze a CPU -- implement 
> memory -- and then load a program and run python on the virtual 
> machine.   When the pentium was first developed, I watched as Intel 
> actually booted up MS-DOS under using Xilinx chips to run the verilog 
> program's output they could physically run anything a pentium processor 
> could run.  That's *IS* what I consider "general purpose".
> 
> But you're sort of confounding my need for type information in my new 
> class as a way to advertise compatability with bool, with subclassing -- 
> which is only one way that I was exploring to get the 'type' name 
> attached to the new object;  That's a mistake that D'Aprano seems to be 
> repetitively making as well.
> But please note: Type checking for 'bool' is only needed for 
> legacy/compatability reasons -- but new code can use any type; so 
> subtyping is not strictly necessary if there is another way to get the 
> 'bool' type attached to my return object for advertising purposes; for 
> what I am interested in is an object who presents as bool for legacy 
> code, but new code can convert it to anything at all..
> 
> C++ *DOES* allow the necessary kind of type checking and subclassing for 
> what I need to do in spite of not having a subclass mechanism built into 
> the language for base types; eg: C++ allows a semantic subclass to be 
> constructed which can be typecast to a bool for compatibility, but 
> otherwise presents extra data and the type the enhanced object reports 
> is irrelevant.  As I've mentioned before, people can do object oriented 
> programming in C,  So, to satisfy your curiosity -- I'll show you a 
> mixed C/C++ example, where I make a semantic subclass that has five 
> values AllFalse, PartFalse, Uncertain, PartTrue, True ; and these five 
> values will have a typeid() of bool and be 100% compatible with legacy 
> C++ bool; but upon request, they these 'bool' types will re-cast into a 
> semantic subtype that provides additional certainty data.
> 
> See the program at end of e-mail.  It compiles with gcc 4.8.2 with no 
> warnings;  g++ filename.cc ; ./a.out
> 
> But let me explain a bit more why I'm picking on Python:  For even if we 
> set the electronic engineering concerns aside that I've raised (and they 
> are valid, as OOP is supposed to model reality, not reality be bent to 
> match OOP) -- People's facile explanations about why Python's version of 
> bool is the way it is -- still bothers me here in the python mail list 
> -- because people seem to have a very wrong idea about bool's nature as 
> a dualton being somehow justified solely by the fact that there are only 
> two values in Boolean logic; For, singletons style programming is not 
> justified by the number of values an object has in reality -- And I know 
> Charles bool didn't use singletons in his algebra,  -- just read his 
> work and you'll see he never mentions them or describes them, but he 
> does actually use dozens of *instances* of the True and False objects he 
> was talking about -- for the obvious reason that he would have needed 
> special mirrors, dichroic or partially silvered, to be even able to 
> attempt to make one instance of True written on paper show up in 
> multiple places; And that's silly to do when there's no compelling 
> reason to do it.
> 
> Yet -- people here seem to want to insist that the bool type with only 
> two *instances* is some kind of pure re-creation of what Charles Bool 
> did -- when clearly it isn't.  It's a amalgamation of enhancements such 
> as binary words instead of just True/False and many other things 
> (operators that work on words rather than single bits.).  So -- I don't 
> see that Python's implementation of Bool is justified by either a purist 
> appeal to Charles bool, or by ignoring pragmatic concerns that have been 
> attached to Bool's work for years by Electrical Engineers in order to 
> make it more useful for *practical* computer problems.  Yet these two 
> things are what this python list has sort of harped on.
> 
> That brings me to your point about other languages;  I think following 
> other languages restrictions arbitrarily is potentially a lemmings 
> approach, eg: just because 'everyone' is doing it statistically does not 
> mean that it is good to do it that way; If many languages do something, 
> there is excellent cause to examine and look for reasons 'why' they do 
> that (and I'd love to hear your opinions) but Python has a different set 
> of constraints as an interpreter, as opposed to a compiler, and many 
> other differences which cause unintended side effects when mimicking 
> other programming languages. It's the unintended side effects and 
> surprises when a hasty decision is made that's the issue here.
> 
> Where python is different from other languages regarding bool -- and 
> deserves a little extra picking on, is that Guido has imposed four 
> constraints *simultaneously* to bool which together cause a conflict 
> that I don't think (offhand) I've ever encountered in another language;  
> Definitely not in C/C++!
> 
> The four things are: 1 -- he cut off subtyping and created no alternate 
> method of doing type checking of duck-types,  2 -- he does not allow 
> multiple instances,  3 -- he himself did not implement bool using the 
> standard alternative methodology to subclassing -- eg: as a composite 
> structure with delegation. 4.  and he has made bool into the default 
> return type for base type comparison operators; which means that general 
> programmers expect a bool for base types and may check for it, even if 
> Python's built in functions do not.
> 
> If any one of these four things had not been done, I would not have 
> reason to complain about bool in Python; because there would be a way 
> for me to easily work with people expecting a bool as a return type from 
> comparison operators, using standard OOP techniques and a little 
> creativity to make something perfectly compatible; rather than having to 
> dig through manuals endlessly with conflicting notions, pep's, and 
> subtleties that make for an extremely steep learning curve and lots of 
> time spent making only slight progress when there's not much *reasoning* 
> behind what Guido did which is consistent and useable as a guideline...
> 
> As far a subtyping goes; The very fact that Guido used subtyping to 
> create bool in the first place (subtype of int), precludes any real 
> claim that bool should not itself be subclassable just because bools 
> only have two values;  I mean, seriously --  Guido's 'strict' Bool is 
> already an impure form of OOP that is borderline hypocrisy, as it can 
> '+' to 2 or 3... and many other things;  and worse I've just come across 
> a couple of papers which suggest that Guido doesn't like subclassing 
> when Composite object structures could be used instead to replace the 
> subclass 'is' relationship with a 'has a' relationship.  So -- if that's 
> the case, why isn't bool a composite to begin with ?  eg: Guido's 
> programming guides must be read with a caveat 'do what Guido says and 
> not what Guido does' ?!
> 
> Now to your last point -- I need to point out that  C++ does not have 
> all four restrictions I've mentioned so it doesn't have the problem 
> Python does;  In C++, there are instances of bool, and therefore I can 
> easily encode extra information in a bool object without changing the 
> object itself.
> 
> Here's a skeleton example, where I only implement one operator '<' on 
> the semantic subclass, but the example shows the principle of how to 
> extend the bool type via typecasting to bool.  There are better ways of 
> doing this, and there are some problems with how I implemented esp. as 
> many use cases are not properly covered -- but it serves to show that 
> C/C++ CAN encode new subtypes (semantic subtypes only not C++ subtypes) 
> while using only the base type itself to transmit data in a perfectly 
> backwards compatible way.  In Python, however, it's pretty close to 
> hopeless...
> 
> #include <iostream>
> #include <typeinfo>
> using namespace std;
> 
> // Create a new super-bool type which is semantically a subtype of bool,
> // But have it masquerade as a bool for compatability, unless new code
> // explicity typecasts it and access its subtype members.
> 
> struct _SBool {
>      bool basebool;
>      int certainty;
> };
> 
> class SBool: public _SBool {
> public:
>      SBool( const bool& );
>      bool operator < (const SBool &);
> };
> 
> // Create all 4 of the statistical uncertainty values as penta-ton.
> const _SBool bools[5] = {{false,0},{false,1},{false,2},{false,3},{true,4}};
> 
> // Create 4 global alias bool names having full compatability with bool
> // for legacy code, but useable in mixed or advanced compares.
> 
> const bool & AllFalse  = bools[0].basebool; // uncertainty 0
> const bool & PartFalse = bools[1].basebool; // uncertainty 1
> const bool & Uncertain = bools[2].basebool; // uncertainty 2
> const bool & PartTrue  = bools[3].basebool; // uncertainty 3
> const bool & True      = bools[4].basebool; // uncertainty 4
> 
> // Create the typecast method.
> SBool::SBool( const bool &b ) {
>      const void* that = &b;
>      if ((that >= bools) && (that < bools+5)) *this=*(const SBool*)that;
>      else *this=*(const SBool*)(const void*) &(b?True:AllFalse);
> 
> bool SBool::operator < (const SBool &other ) {
>      return this->certainty < other.certainty;
> }
> 
> // ------------------------------------  Test harness.
> int main(void) {
>      cout << "type match=" <<  (typeid(bool) == typeid(AllFalse)) << endl;
>      cout << "testing as bool "       << AllFalse << PartFalse << 
> Uncertain << PartTrue << True << endl;
>      cout << "testing as SBool "      << SBool(PartFalse).certainty << 
> endl;
>      cout << "testing up-cast false " << SBool(false).certainty << endl;
>      cout << "testing up-cast true "  << SBool(true).certainty << endl;
>      cout << "testing advanced compare (should be true)" << 
> (SBool(AllFalse) < PartFalse) << endl;
>      cout << "testing legacy compare (should be false) " << (AllFalse < 
> PartFalse) << endl;
>      return 0;
> }
> 
> //------------------------------------ End of program, Test output 
> follows -------------------
> 
> type match=1
> testing as bool 00001
> testing as SBool 1
> testing up-cast false 0
> testing up-cast true 4
> testing advanced compare (should be true)1
> testing legacy compare (should be false) 0bash-4.2$

Can you tell me what of the following code does not satisfy your requirements?
[Needs python 3.4]


>>> from enum import IntEnum
>>> class B4(IntEnum):
	F1 = 0
	F2 = 0
	F3 = 0
	T  = 1

In words:
Thats a type of 4-valued boolean
Of which F1/2/3 behave falsey in standard python bool-expecting contexts
T behaves truey (or truish)
[Check with bool(B4.F1) for example]

If you get fed up with typing B4.blah make global variables (actually constants)
F2 = B4.F2

If you need to distinguish the falsey ones, its a bit of a headache
dict(B4.__members__)
should contain all the info you need to make these distinctions



More information about the Python-list mailing list