Page 1 of 2

Unwelcome changes with strings in expressions with Bool()

Posted: Wed Dec 18, 2013 6:27 am
by Mistrel
I have been using PureBasic 4.60 up until recently and there are indeed a lot of changes. However, this one inparticular breaks practically ALL of my code, is not intuitive, and makes PureBasic's strings feel like second-class citizens.

This doesn't even make sense.. as a string in PureBasic is considered to be a fully qualified type then the syntax should be the same as every other type; it still works for all of the others!

I can no longer do this:

Code: Select all

If Not Empty.s
  Debug 1
EndIf
The new syntax is:

Code: Select all

If Not Bool(Empty.s)
  Debug 1
EndIf

or

If Empty.s=""
  Debug 1
EndIf

or

If Len(Empty.s)
  Debug 1
EndIf
The compiler error literally says:
Line 1: 'Not' operand can not be used with strings.
Which suggests that it probably has all of the information needed already to make the evaluation.. but a design choice was made such that it no longer does.

This makes me very sad and is an unwelcome change. I am so used to simply using "Not" when referring to an empty string that adjusting to this has been more than a little mind-numbing.

I accept that Bool() can be useful for removing ambiguity but this change is a significant step backwards in terms of ease of use. Please PLEASE consider changing this back. :(

Re: Unwelcome changes with strings in expressions with Bool(

Posted: Wed Dec 18, 2013 9:28 am
by Little John
This was a deliberate change, so the "Bugs" subforum is not the proper place for talking about it.
Mistrel wrote:I have been using PureBasic 4.60 up until recently and there are indeed a lot of changes. However, this one inparticular breaks practically ALL of my code, is not intuitive, and makes PureBasic's strings feel like second-class citizens.

This doesn't even make sense
The change makes a lot of sense, but writing

Code: Select all

If Not Empty.s
  Debug 1
EndIf
never made sense, because strings are not and never were boolean expressions.

If Not Empty.s is logically equivalent to If Empty.s = #False.
AFAIR If Empty.s = #False never worked in PB, and it is nothing but clean and consistent that If Not Empty.s now does not work as well.

Use

Code: Select all

If x$ = ""
   ; ...
Endif
instead.
This was, is, and will be correct in the future. It is also good readable and self-explanatory.

Re: Unwelcome changes with strings in expressions with Bool(

Posted: Wed Dec 18, 2013 5:37 pm
by Mistrel
The new syntax is:

Code: Select all

If Not Bool(Empty.s)
My point is that this code literally says "evaluate this string as a boolean" .. but the expression already demands this as it's using a boolean operator. I shouldn't have to explicitly say "yes, this is REALLY a boolean"; the parser already knows this, ESPECIALLY in this case because there is only one thing being evaluated!

We don't write this:

Code: Select all

If Not Bool(Number)
Because in terms of a number there are only two obvious states to be evaluated as a boolean: it is either 0 or it is NOT. The same is with a string. It is either empty or it is NOT.

The change is more along the lines of a decision to remove this functionality for an interpretation of correctness. However, removing native boolean functionality on a core type is a big change, and, whether or not we argue semantics on how correct it really is, it was one of my FAVORITE features of PureBasic strings. It was easy as pie to evaluate strings like this.

It made sense.. if you are referring to a string AS a boolean then it has two states: it's either empty or it's not. So instead of going through the whole "is it = "" .. which is the only thing it could (boolean) NOT be" I could just write "Not".

Re: Unwelcome changes with strings in expressions with Bool(

Posted: Wed Dec 18, 2013 6:33 pm
by netmaestro
Maybe it's just natural paranoia, I don't know but I've never been comfortable with doing this:

Code: Select all

If somestring.s
  ; do this
Else
  ; do that
Endif
When I'm writing code that matters at all, I've always gone with

Code: Select all

If somestring.s <> ""
  ; do this
Else
  ; do that
Endif
I just never have been able to bring myself to trust the other syntax.

Re: Unwelcome changes with strings in expressions with Bool(

Posted: Wed Dec 18, 2013 9:07 pm
by Mistrel
My coding style shortens all instances of "If It-Is-Not" to "If Not". This way when I read code I can generally tell from the left side whether something is being tested against as a true or false expression by the left side of the expression.

Testing against:

Code: Select all

If String.s=""
is kind of a head-fake because you're testing for equality which moves the boolean from the operator outside of the expression to the one inside. This requires a read through of the whole expression.

Across a large code base, that can turn out to be a lot of extra work for something that could otherwise be determined by reading only the outside operator only.

I don't really understand the need for Bool() to be REQUIRED for string expressions. Not all string expressions can be determined at compile time; and I dare that that the vast majority are not, given the dynamic nature of strings. So why not just provide it as a means to explicitly label a string expression for compile-time optimization rather than forcing it on absolutely everything.

Re: Unwelcome changes with strings in expressions with Bool(

Posted: Wed Dec 18, 2013 9:26 pm
by Little John
Mistrel wrote:Testing against:

Code: Select all

If String.s=""
is kind of a head-fake because you're testing for equality which moves the boolean from the operator outside of the expression to the one inside. This requires a read through of the whole expression.
:?:

That expression can be True or False, but a string alone can't be True or False, because it's no Boolean variable.
Just use Boolean operators for Boolean variables, and string operators for string variables etc.
With such clean handling of different data types, there is no problem at all.

Re: Unwelcome changes with strings in expressions with Bool(

Posted: Wed Dec 18, 2013 9:47 pm
by Shield
Little John wrote:...but a string alone can't be True or False, because it's no Boolean variable.
If you argue like this, then...

Code: Select all

If string
   Debug "Not Empty"
EndIf
...should not be allowed as well, because "a string is not a boolean value".
In this case, a non-empty string is treated as 'boolean true', since the execution
enters the If-block. Therefore If Not should be allowed as well because, apparently,
a string can be used directly in a condition...and the conclusion follows that this
condition can be negated by the Not operator.

I do agree that strings need to be treated differently, but using If string and If Not string
makes total sense in this case and I used it often as well while it was allowed.

Re: Unwelcome changes with strings in expressions with Bool(

Posted: Wed Dec 18, 2013 10:01 pm
by skywalk
The old undocumented behavior was confusing at 1st, but definitely easy on the eye.
Bool() is a welcome addition and strings should be fully compared logically. Else, users from VB land will ask Why Does "0" = #True? :)

Re: Unwelcome changes with strings in expressions with Bool(

Posted: Thu Dec 19, 2013 12:59 am
by PMV
A string can be logical true or false, if the language defines it.
Fred has defined PB as "if String.s" to be logically true, if
String.s is not empty. And he has said, that "If Not Strings.s"
was never supported and just luckily worked, so he removed
it to clean it up.

Thats the story behind it. :wink:
I liked "If Not String.s" but as long as he likes it that why,
it is nothing else as If String.s <> "". Old code has to
be modified to be save.

I really don't remember when he said that. It was in one
of the threads with the same topic as this one :wink:

MFG PMV

Re: Unwelcome changes with strings in expressions with Bool(

Posted: Thu Dec 19, 2013 6:10 am
by Shield
It's just yet another inconsistency...

Re: Unwelcome changes with strings in expressions with Bool(

Posted: Thu Dec 19, 2013 8:12 am
by Danilo
Please make both officially supported:

Code: Select all

If string
    ; do something, if string is not empty
Endif

Code: Select all

If Not string
    ; do something, if string is empty
Endif

Re: Unwelcome changes with strings in expressions with Bool(

Posted: Thu Dec 19, 2013 8:17 am
by Shield
Exactly my thoughts. The alternative would be to also disallow "If string"
and force it to be "If string <> "". I'd certainly be in favor of the first...

Re: Unwelcome changes with strings in expressions with Bool(

Posted: Thu Dec 19, 2013 8:26 am
by ts-soft
Danilo wrote:

Code: Select all

If Not string
    ; do something, if string is empty
Endif
Is a nil-string empty? or only a ""-string?

Code: Select all

Define.s str1, str2 = ""

Debug @str1
Debug @str2

Re: Unwelcome changes with strings in expressions with Bool(

Posted: Thu Dec 19, 2013 8:28 am
by Danilo
Of course both are empty. Both strings do not contain characters.

You can already check for nil-string with

Code: Select all

Define.s str1, str2 = ""

If @str1
    Debug "str1 not nil-string"
EndIf

If Not @str1
    Debug "str1 is nil-string"
EndIf
Please notice that "If Not xxx" works with numbers. No explicit comparison operator required. ;)
In case of numbers it means the number is 0. In case of strings, it should check if the string actually contains characters or is empty/nil.

Re: Unwelcome changes with strings in expressions with Bool(

Posted: Thu Dec 19, 2013 8:29 am
by Shield
Len(str1) = 0, so it is empty...
If str1 is false, so it is empty...