how will the behaviour be with arrays or multisets?
zero_type(({ UNDEFINED })[0]); // this is 1 array a = ({ UNDEFINED }); zero_type(a[0]); // this is 0
Well, it's not really an interesting case, because when you try to index something that has no index in an array you get an exception (like a[1] in this case).
This seems like a rather pike centric view arguing that UNDEFINED is a technical storage property of something (_the index foo_ of an array is not defined, rather than _the value stored at index foo_ is the undefined value often called null -- where the latter is more useful behaviour in practice).
At least this quoted example led me into believing that we are indeed upgrading the UNDEFINED value to a storable NULL value:
mapping m = ([ "x" : 0, "y" : UNDEFINED, ]);
zero_type( m->x ); // This should be 0 zero_type( m->y ); // This should be 1 zero_type( m->z ); // This should be 1
has_index( m, "x" ); // This should be 1 has_index( m, "y" ); // This should be 1 has_index( m, "z" ); // This should be 0
...where zero_type, in a scenario where this instead held:
has_index( m, "z" ); // This should be 1
would have let us use ->= to do m_delete in scenarios like m->z=foo(); (which could be useful at times, if probably more rarely).
If the aim is not to make UNDEFINED a proper storable null value, what is the goal with these changes? I'm not sure I've figured it out yet.