On Tue, 25 Oct 2011 22:19:29 +0200, Antonis Tsiapaliokas
<kok...@gmail.com> wrote:
> Also, please read the comment from the John Brooks, which i think that
> he isright. So what do you think?
I would say he is right. He strongly hints at the possibility that bool is
too context dependent. And I agree with that.
This thing is tricky to tackle. QString was created to easily handle
localization. Chances are you are going to not only interpret true/false,
but also ja/(nee|nein|nej), oui/non, si/no and whatever may mean true or
yes (or OK?) in whatever language. What if a language introduces a new
word to mean true? You just don't have to handle natural language issues
with doubles, floats and integers, which is why that can be done by
QString hands down.
I think deciding on the meaning of a string is one of the things better
left to its user. Outside the string you know exactly what you expect. A
number, a word, what language the word is going to be in, which words are
going to mean 'true', which are 'false' and which should produce an error.
bool yes = (str.toInt() != 0);
bool yes = (str.compare(tr("true"), Qt::CaseInsensitive) == 0);
bool yes = (str.compare("true", Qt::CaseInsensitive) == 0);
bool yes = QVariant(str).toBool(); // tricky but might work
Based on the fact that you need a lot of information to correctly
interpret the string into a boolean value, I would say this can't really
cover a lot of common cases without being a hackish blob of code. It is
probably better to not include this in QString.
Cheers,
Frans
_______________________________________________
Development mailing list
Devel...@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development
QVariant has toBool just like it has toDouble and toInt, so I think it makes
sense to have it in QString and in QByteArray.
So I recommend:
1) document very well what is true and what isn't
2) make sure all three classes work the same way. If not, change them so that
they all have toBool() const and they all operate equally.
3) add unit tests
4) ensure that QVariant::toBool calls into QString::toBool and
QByteArray::toBool, as applicable. Note pending the commits by Jędrzej that
are refactoring the QVariant internals.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
On Tue, 25 Oct 2011 23:01:43 +0200, Thiago Macieira <thi...@kde.org> wrote:
> QVariant has toBool just like it has toDouble and toInt, so I think it
> makes sense to have it in QString and in QByteArray.
It makes sense from an equal-API point of view. On the other hand,
QVariant has a significantly different task than QString does -- QString
is, AFAIK, not a union replacement like QVariant is. Does it make sense to
add QString::toBool() from a basic task perspective?
> 1) document very well what is true and what isn't
Restricting the use to e.g. English only, would not be really useful when
parsing (localized) user input, although I don't think this would happen a
lot. I only know of a few cases where an end-user is expected to
explicitly type yes or no into an input field, and those are command line
tools. Wouldn't that be pretty much the only use case?
I might have overlooked things. It's getting late anyway.
> 2) make sure all three classes work the same way. If not, change them so
> that they all have toBool() const and they all operate equally.
>
> 3) add unit tests
>
> 4) ensure that QVariant::toBool calls into QString::toBool and
> QByteArray::toBool, as applicable. Note pending the commits by Jędrzej
> that are refactoring the QVariant internals.
If QString::toBool() is added, would there also be a need for something
like static QString::boolean(bool value, char format = 't')?
I agree with your argument, I just don't think it's applicable. QString is not
localised and has never promised to be. QString::number generates C-locale
numbers and toInt/toDouble parse C-locale; QDate::toString generates C-locale
dates (or should), etc. If you want localised information, you should use
QLocale.
> > 2) make sure all three classes work the same way. If not, change them so
> > that they all have toBool() const and they all operate equally.
> >
> > 3) add unit tests
> >
> > 4) ensure that QVariant::toBool calls into QString::toBool and
> > QByteArray::toBool, as applicable. Note pending the commits by Jędrzej
> > that are refactoring the QVariant internals.
>
> If QString::toBool() is added, would there also be a need for something
> like static QString::boolean(bool value, char format = 't')?
It's much easier to use the ternary operator and just select which option you
want to use.
> Consider this code:
>
> bool parseOk;
> if (str.toBool(&parseOk)) {
> if (parseOk)
> enableSuperFastRenderer();
> }
I think that in most, if not all cases, the parseOk argument would or
even should be omitted (just like with QVariant):
if (str.toBool()) {
enableSuperFastRenderer();
}
because the results will be exactly the same as your example.
> then this:
>
> if (str == QLatin1String("true")) {
> enableSuperFastRenderer();
> }
>
> which would you prefer?
I ask you the same question.
Cheers,
Frans
> I agree with your argument, I just don't think it's applicable. QString is not
> localised and has never promised to be. QString::number generates C-locale
> numbers and toInt/toDouble parse C-locale; QDate::toString generates C-locale
> dates (or should), etc. If you want localised information, you should use
> QLocale.
Given that information and assuming that the results match QVariant,
I don't see any reason not to include QString::toBool(). The
assumption will obviously always be valid if QVariant uses
QString::toBool() for parsing.
>> If QString::toBool() is added, would there also be a need for something
>> like static QString::boolean(bool value, char format = 't')?
>
> It's much easier to use the ternary operator and just select which option you
> want to use.
Consider:
bool b = true;
QString str1 = b?"treu":"false";
if (str1.toBool()) {
// we never get here...
}
QString str2 = QString::boolean(b);
if (str2.toBool()) {
// we will get here
}
This example might be a bit far-fetched and I do agree that the
advantage, if any, would be fairly small. QString::boolean() would
always produce a value that is guaranteed to be correctly parsed by
QString::toBool(). The ternery operator not so much. Also the user
doesn't have to explicitly know about which values evaluate to true in
QString::toBool() to enter the correct value; from an API perspective
I think it would make sense to enable a black-box round-trip.
I agree with Jan Arve on this topic. You need to have verification that
a conversion succeeded.
André
> IMHO, there is a big difference between a string that correctly converts
> to false, and one that can not be converted to a boolean. Do you really
> wish to make that difference invisible?
Certainly not.
> I agree with Jan Arve on this topic. You need to have verification that
> a conversion succeeded.
I do agree that you need to have the verification available, however,
I daresay in a lot of cases the need for it is not that big. I at
least don't care if or why a boolean conversion fails in a lot of
cases (with QVariant currently).
Then there's readability for slightly more complex situations.
Assuming that QString::toBool() acts like QVariant::toBool() and
returns true if the contents are "1", "true", or "y", false otherwise,
consider the following:
bool ok;
bool result = str.toBool(&ok);
if (ok) {
if (result)
enableSuperFastRenderer();
else
disableSuperFastRenderer();
} else {
doSomethingSmart();
}
against
if (str.compare("true", Qt::CaseInsensitive) == 0
|| str.compare("y", Qt::CaseInsensitive) == 0
|| str == "1" ) {
enableSuperFastRenderer();
} else if (str.compare("false", Qt::CaseInsensitive) == 0
|| str.compare("n", Qt::CaseInsensitive) == 0
|| str == "0") {
disableSuperFastRenderer();
} else {
doSomethingSmart();
}
If I had the choice, I'd take the first option over the second.
And honestly, what are the odds someone instead would write:
if (str == QLatin1String("true")) {
enableSuperFastRenderer();
} else {
disableSuperFastRenderer();
}
What would you do if you couldn't parse string. Make the assumption
you can, and enable the super fast renderer?
All at the risk of playing the devil's advocate, of course.
Cheers,
Frans
bool parseOk
if (!str.toBool(&parseOk) && parseOk)
disableSuperFastRenderer();
Or you can accept that, if the user types crap instead of "false", it's false.
>
> What would you do if you couldn't parse string. Make the assumption
> you can, and enable the super fast renderer?
I *might* want to bail out and warn the user, but it depends on the
situation, of course.
André
> Note that the verification flag would be optional anyway. If you return
> false if ok is false, then you can easily choose if you need
> verification or not. It just needs to be clearly documented.
As always.
> However, if
> you think that it would be good for readability, wouldn't it then make
> sense to have a way to do this in a localized way as well? The various
> true & false strings could conceivably be in QLocale? Otherwise, you
> still end up in the same situation if your application needs
> localization (and most do, I think).
The localized way should be done the same way as one would handle
localized numbers (like properly handling 1,234.56 and 1.234,56).
>> What would you do if you couldn't parse string. Make the assumption
>> you can, and enable the super fast renderer?
> I *might* want to bail out and warn the user, but it depends on the
> situation, of course.
Of course. I would think however that in these cases you shouldn't
really be explicitly relying on QString::toBool(), but that is a
completely different discussion altogether.
I think we should then really discuss about what should be considered
to be "true" (and what to be "false", so we also figure out if a "bool
*ok" parameter is actually needed or not). In my humble opinion, a
case insensitive comparison against the string "true" is too generic
and weak (not to mention English-only). If that's a way of checking
some user input I think it's simply a bad idea to have it inside
QString.
For instance, Perl thinks that empty string and the literal "0" are
false, and any other string is true. In Python and JS only the empty
strings are false. Should Qt do something similar?
--
Giuseppe D'Angelo
As far as I remember, POSIX locales offer strings or regexps for YES
and NO, so it might be possible to add something to QLocale to access
those strings.
--
Christoph Feck
http://kdepepo.wordpress.com/
KDE Quality Team
By auto-converting a QString to a bool we'll be adding ambiguity to Qt
APIs. If there's no intuitive way to convert a QString to a boolean,
then QString IMO should not provide that as a function... I find it
especially disturbing that translatability and locale is considered.
Literal interpretation of a string needs to be completely unambiguous,
just like QString("123").toInt() is.
If we add QString::toBool(), I think we are adding future bugs to
applications that make use of this function. We'll find code that
calls toBool() on all kinds of strings with hard-to-read outcomes.
QString(QChar::Null).toBool()
QString("0").toBool()
QString("null").toBool()
QString("nil").toBool()
QString().toBool()
QString("false").toBool()
QString("no").toBool()
QString("not").toBool()
QString("!").toBool()
QString("negative").toBool()
Do any of these examples have any _intuitive_, unambiguous return values?
I vote -1 on this feature. Just write:
if (value == "true")
{
}
or
if (value.compare("true", Qt::CaseInsensitive) == 0)
{
}
or write a grammar and a proper parser :-).
--
Andreas Aardal Hanssen
*If* QString::toBool is introduced, there needs to be a properly
localized or at least localizable version in QLocale as well, I think.
André
Right: that needs to be fixed: QString should operate ONLY on the C locale. If
you need anything with other locales, it should be clearly marked (like "%L1"
in arg()) or you should use QLocale.
The same goes for QDate and QTime. Does anyone volunteer to do this change?
>
> If QString::toBool is introduced, there needs to be a properly
> localized or at least localizable version in QLocale as well, I think.
>
> André