On 01/15/2015 09:05 AM, Ian Kelly wrote:
On Thu, Jan 15, 2015 at 12:23 AM, Andrew Robinson
<andr...@r3dsolutions.com> 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$













--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to