May 10, 2017
On Wednesday, May 10, 2017 12:06:40 Ali Çehreli via Digitalmars-d wrote:
> On 05/10/2017 11:49 AM, Jonathan M Davis via Digitalmars-d wrote:
>  > On Wednesday, May 10, 2017 05:05:59 Ali Çehreli via Digitalmars-d
wrote:
>  >> On 05/09/2017 10:34 AM, H. S. Teoh via Digitalmars-d wrote:
>  >>  > After upgrading the compiler, I get a warning that using a
>
> pointer as a
>
>  >>  > condition is deprecated.
>  >
>  > I think that that's the one that Andrei and Vladimir didn't like,
>  > because
>  > they actually used the conversion to bool correctly in their code a
>  > bunch
>  > (whereas most everyone else thought that it was too error prone), and
>  > the
>  > deprecation ended up being removed.
>  >
>  > - Jonathan M Davis
>
> Bummer for H. S. Teoh I guess... :/
>
> Although I prefer explicit over implicit in most cases, I've never
> graduated from if(p) and still using it happily. :)

The big problems is dynamic arrays, not pointers, which was what I thought that H. S. Teoh was talking about (apparently, I read over what he said too quickly). I don't know about deprecations with pointers and if statements, and I use pointers sparingly enough in D that I don't know how long it would be before I'd notice if it _were_ deprecated. But with dynamic arrays, it checks for null, not for empty, and a bunch of folks tend to assume that it checks for empty. Using dynamic arrays directly in if conditions is what had been deprecated (on the theory that it was too error-prone) and what Andrei and Vladimir were unhappy about.

- Jonathan M Davis


May 11, 2017
On Wednesday, 10 May 2017 at 19:06:40 UTC, Ali Çehreli wrote:
> Bummer for H. S. Teoh I guess... :/
>
> Although I prefer explicit over implicit in most cases, I've never graduated from if(p) and still using it happily. :)
>
> Ali

All bool conversions in D are value based, not identity based. Not only this is error prone, this is inconsistent.
May 11, 2017
On Wednesday, 10 May 2017 at 19:06:40 UTC, Ali Çehreli wrote:
> On 05/10/2017 11:49 AM, Jonathan M Davis via Digitalmars-d wrote:
> > On Wednesday, May 10, 2017 05:05:59 Ali Çehreli via
> Digitalmars-d wrote:
> >> On 05/09/2017 10:34 AM, H. S. Teoh via Digitalmars-d wrote:
>
> >>  > After upgrading the compiler, I get a warning that using
> a pointer as a
> >>  > condition is deprecated.
>
> > I think that that's the one that Andrei and Vladimir didn't
> like, because
> > they actually used the conversion to bool correctly in their
> code a bunch
> > (whereas most everyone else thought that it was too error
> prone), and the
> > deprecation ended up being removed.
> >
> > - Jonathan M Davis
>
> Bummer for H. S. Teoh I guess... :/
>
> Although I prefer explicit over implicit in most cases, I've never graduated from if(p) and still using it happily. :)
>
Yes, me too (in C). It is conceptually imho ok to use it that way as a pointer does have a boolean semantic, either it is a valid pointer or it is not. The value of the pointer itself is only in special cases relevant (cases in which they have to be converted to an integral type anyway) and is in any case extremely machine dependent.
One can even make the case that checking "ptr !is null" or in C "ptr != 0" is inconsistent as it is the only operation where the value of a pointer is used, which is, at least for C a source of confusion. The 0 value in a pointer context will not necessarily compile to a 0 value in the generated assembly. Some machines have null ptrs that are not represented by 0 bits integral values and the C standard has to take these (granted obsolete) into account.


May 11, 2017
On 5/10/17 2:49 PM, Jonathan M Davis via Digitalmars-d wrote:
> On Wednesday, May 10, 2017 05:05:59 Ali Çehreli via Digitalmars-d wrote:
>> On 05/09/2017 10:34 AM, H. S. Teoh via Digitalmars-d wrote:
>>  > I even appreciate breakages that eventually force me to write more
>>  >
>>  > readable code!  A not-so-recent example:
>>  >    /* Used to work, oh, I forget which version now, but it used to
>>  >
>>  >     * work: */
>>  >
>>  >    MyType* ptr = ...;
>>  >    if (someCondition && ptr) { ... }
>>  >
>>  > After upgrading the compiler, I get a warning that using a pointer as a
>>  > condition is deprecated.  At first I was mildly annoyed... but then to
>>  >
>>  > make the warning go away, I wrote this instead:
>>  >    /* Look, ma! Self-documenting, readable code! */
>>  >    MyType* ptr = ...;
>>  >    if (someCondition && ptr !is null) { ... }
>>
>> Can you show an example please. I don't see this being required by
>> 2.074.0 (compiled with -w -de).
>
> I think that that's the one that Andrei and Vladimir didn't like, because
> they actually used the conversion to bool correctly in their code a bunch
> (whereas most everyone else thought that it was too error prone), and the
> deprecation ended up being removed.

I think that was the if(array) fiasco.

I don't ever remember if(ptr) being deprecated. In fact, I'd go as far as saying that maybe H.S. Teoh misremembers the array thing as pointers.

The biggest reason is that a huge useful pattern with this is:

if(auto x = key in someAA)
{
   // use *x without more hash lookup costs.
}

I can't imagine anyone attempted to force this to break without a loud backlash. I think if(ptr) is mostly universally understood to mean the pointer is not null.

-Steve
May 11, 2017
On 5/11/17 5:37 AM, deadalnix wrote:
> On Wednesday, 10 May 2017 at 19:06:40 UTC, Ali Çehreli wrote:
>> Bummer for H. S. Teoh I guess... :/
>>
>> Although I prefer explicit over implicit in most cases, I've never
>> graduated from if(p) and still using it happily. :)
>>
>> Ali
>
> All bool conversions in D are value based, not identity based. Not only
> this is error prone, this is inconsistent.

What does "value based" and "identity based" mean?

bool conversions vary widely and allow a lot of flexibility (at least for structs):

if(arr) -> same as if(arr.ptr)
if(someInt) -> same as if(someInt != 0)
if(someObject) -> if(someObject !is null && someObject.invariant)
if(someStruct) -> if(someStruct.opCast!(bool))

-Steve
May 11, 2017
On Thursday, 11 May 2017 at 12:21:46 UTC, Steven Schveighoffer wrote:
> I can't imagine anyone attempted to force this to break without a loud backlash. I think if(ptr) is mostly universally understood to mean the pointer is not null.
>
> -Steve

It is not a problem for pointer because for pointer identity and equality are the same thing. It isn't for slices.
May 11, 2017
On Thursday, 11 May 2017 at 12:26:11 UTC, Steven Schveighoffer wrote:
> if(arr) -> same as if(arr.ptr)

Nope. It is:

if(arr) -> same as if(((cast(size_t) arr.ptr) | arr.length) != 0)

Should we conclude from the fact that absolutely nobody gets it right in this very forum that nobody will get it right outside ? I'll let you judge.

May 11, 2017
On 5/11/17 7:12 PM, deadalnix wrote:
> On Thursday, 11 May 2017 at 12:26:11 UTC, Steven Schveighoffer wrote:
>> if(arr) -> same as if(arr.ptr)
>
> Nope. It is:
>
> if(arr) -> same as if(((cast(size_t) arr.ptr) | arr.length) != 0)
>
> Should we conclude from the fact that absolutely nobody gets it right in
> this very forum that nobody will get it right outside ? I'll let you judge.
>

Yep, you are right. It's checking the length too. Although in practice, almost never do you have a null pointer array with non-zero length.

Just for your amusement, I wrote the test this way :)

Stevens-MacBook-Pro:testd steves$ cat testifarrptr.d
void main()
{
    char[] x = null;
    x = x.ptr[0 .. 1];
    if(x)
    {
        import std.stdio;
        writeln("ok, deadalnix was right");
    }
}
Stevens-MacBook-Pro:testd steves$ dmd -run testifarrptr.d
ok, deadalnix was right


-Steve
May 11, 2017
On Thu, May 11, 2017 at 08:21:46AM -0400, Steven Schveighoffer via Digitalmars-d wrote: [...]
> I don't ever remember if(ptr) being deprecated. In fact, I'd go as far as saying that maybe H.S. Teoh misremembers the array thing as pointers.
> 
> The biggest reason is that a huge useful pattern with this is:
> 
> if(auto x = key in someAA)
> {
>    // use *x without more hash lookup costs.
> }
> 
> I can't imagine anyone attempted to force this to break without a loud backlash. I think if(ptr) is mostly universally understood to mean the pointer is not null.
[...]

Since the accuracy of my memory was questioned, I went back to look at the code in question, and indeed I did misremember it, but it was not with arrays, it was with casting pointers to bool.  And it was in a while-condition, not an if-condition.  Here's a simplified version of the original code:

	struct Op {...}
	Op* getOp(...) { ... }
	...
	Op* op;
	while (!input.empty && cast(bool)(op = getOp(...))) { ... }

The cast(bool) used to be accepted up to a certain version (it was in
the code from when I first wrote it around 2012), then around 2013 it
became a compile error, which forced me to rewrite it as:

	struct Op {...}
	Op* getOp(...) { ... }
	...
	Op* op;
	while (!input.empty && (op = getOp(...)) !is null) { ... }

which is much more readable and documents intent more clearly.

I originally wrote the cast(bool) because without it the compiler rejects using assignment in an while-condition.  I suppose the reasoning is that it's too easy to mistakenly write `while (a=b)` instead of `while (a==b)`. In modern C compilers, an extra set of parentheses usually silenced the compiler warning about a possible typo of ==, but in D even with parentheses the compiler would reject it.

So all things considering, this little anecdote represents the following progression in readability (the first 2 steps are hypothetical, since they're only permitted in C):

	while (a = b) ...		// in C, error-prone, could be typo
	while ((a = b)) ...		// still in C, marginally better
	while (cast(bool)(a = b))	// early D, the conversion is now explicit
	while ((a = b) !is null)	// present-day D, finally intent is clear


T

-- 
By understanding a machine-oriented language, the programmer will tend to use a much more efficient method; it is much closer to reality. -- D. Knuth
May 11, 2017
On 5/11/17 7:12 PM, deadalnix wrote:
> On Thursday, 11 May 2017 at 12:26:11 UTC, Steven Schveighoffer wrote:
>> if(arr) -> same as if(arr.ptr)
>
> Nope. It is:
>
> if(arr) -> same as if(((cast(size_t) arr.ptr) | arr.length) != 0)
>
> Should we conclude from the fact that absolutely nobody gets it right in
> this very forum that nobody will get it right outside ? I'll let you judge.
>

But this still doesn't mean that *all* bool conversions are value based. In at least the struct and class cases, more than just the bits are checked.

-Steve