Comparisons and sorting of a numeric class....
Rustom Mody
rustompmody at gmail.com
Fri Jan 23 10:31:29 EST 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