On Tue, Jun 25, 2024, at 20:23, Ilija Tovilo wrote:
> Hi Rob
> 
> On Tue, Jun 25, 2024 at 9:05 AM Rob Landers <rob@bottled.codes> wrote:
> >
> > On Tue, Jun 25, 2024, at 01:20, Ilija Tovilo wrote:
> >
> > On Mon, Jun 24, 2024 at 9:54 PM Robert Landers <landers.rob...@gmail.com> 
> > wrote:
> > >
> > > To be honest, this is one of the smaller concerns I have with the new
> > > syntax. There might be some misunderstanding here, though. A
> > > non-existent key is NULL, always has been, and always will be.
> >
> > This is just not accurate. Inexistent indexes are not null in PHP,
> > they are undefined. PHP implicitly coerces undefined to null, because
> > undefined is not a value accessible to users. The same occurs when
> > accessing $undefinedVariable. For arrays, this fact is observable
> > through `foreach`, warnings when accessing the index, and likely
> > others.
> >
> > This is a bit like telling someone who fell off a ladder that they didn’t 
> > “technically” fall, instead the Earth and them pulled at each other until 
> > they collided and the ground + body absorbed the energy.
> >
> > While yes, you are “technically” correct, what you describe is essentially 
> > unobservable from the context of the running code (unless you turn the 
> > warning into an error/exception). For all direct accesses of array values 
> > ($arr['key']) an array is infinitely full of nulls (I have actually 
> > depended on this property at one point for a bloom filter).
> 
> If null array values were indeed unobservable, then [] would be === to
> [null] (or at least ==), and a foreach over [null] would result in 0
> iterations. But neither of those are the case.

I think there is a difference between an empty array and a null, and that is 
(hopefully) self-evident. I’m talking about the infinite nulls IN the array. 
You can write a for loop of all possible keys until the end of the universe, 
and all you will get is null. This is fairly easy to prove. I'll wait... :p

> 
> > So yes, `[?'foo' => string]` and `['foo' => ?string]` are indeed
> > different. The former accepts `[]`, while the latter accepts `['foo'
> > => null]`.
> >
> > Are they actually different in practice though? That was my point. After 
> > the “is” in both cases, you’ll have to use null-coalescence to retrieve the 
> > value. For all intents, they are the same resulting code. If you can show a 
> > difference in the resulting code and how it is an improvement, I may be 
> > inclined to agree, but I can’t think of one.
> 
> Sure. If a null value were to mean "not set", then ['foo' => string]
> should accept ['foo' => 'foo', 'bar' => null], which is absolutely
> observable if the code assumes it won't see any additional indexes.

The only way you’d observe this (that I can think of) is by performing a 
for-each loop over the array. In this case, I can't think of a reason you would 
assert the shape of individual keys beforehand. Maybe someone who would do that 
can chime in with a realistic example.

What I was talking about is something like this:

$hasFoo = $arr is [?'foo' => string];

// if I understand the RFC correctly, $hasFoo is true for [] and ['foo' => 
'some-string']
if ( $hasFoo ) {
  $foobar = $arr['foo'] ?? null;
}

Now with the alternative:

$hasFoo = $arr is ['foo' => ?string];

// in theory, this matches [], ['foo' => null] and ['foo' => 'some-string']
if ( $hasFoo ) {
  $foobar = $arr['foo'] ?? null;
}

Note that the actual code *did NOT* change. What we have is that in the first 
example, a person well-versed in PHP is going to wonder why `($hasFoo is false) 
=== true` and `($arr['foo'] is null) === true`. It's logically inconsistent 
with itself because we clearly specified that it shouldn't exist but it does 
exist and the value is NULL.

Yeah, it's weird that arrays are infinitely full of null, but surprisingly 
useful. If we don't like it, we can always create an RFC to treat non-existent 
keys as an error instead of a warning.
  

> 
> Ilija
> 

— Rob

Reply via email to