length of null array = 0

BlitzMax Forums/BlitzMax Programming/length of null array = 0

Bobysait(Posted 2016) [#1]
I don't know if it's how it's supposed to be, but length of null arrays returns "0".
in some way it makes sens, but shouldn't it crashes with an access to a Null pointer ?

Type Ta
	Field length:Int
End Type

Local a:Ta[];
Print a.length
Print a<>Null

Local t:Int[]
Print t.length
Print t<>Null




Brucey(Posted 2016) [#2]
No, because a non-initialised array is internally an instance of a special empty array.


Yasha(Posted 2016) [#3]
String and array variables can't actually be Null in the sense of having the same object identity as any other type variable set to Null. They both instead return objects with length 0, because as you can see, that's simply more useful in this case.

There is one area where you need to be careful though, and that's if you tend to store a lot of things in variables of type Object. There are a couple of edge cases where BlitzMax doesn't, or can't, insert the implicit conversion (between bbNullObject and bbEmptyArray), and as a result it's possible - if unlikely - to end up writing code that compares Null to Null and ends up false or whatever. Will add example if I can find it.


Anyway, the general name for this particular way of handling non-values is the Null Object Pattern (or sometimes Nil Object Pattern, to distinguish it from Null). Under this pattern, instead of marking "absent" values with an inaccessible non-value like the null pointer, there are instead valid "zero" values defined for each type that always provide a correct response to field reads or method calls, but simply do nothing. This is useful in many places: BlitzMax uses it internally in its implementation of TMap, for instance, to avoid having to write an extra "If Null" test when navigating the tree (instead, the leaves are nil objects that simply don't return anything or navigate further).

It would be nice to support this at a language level and be able to tell types not to use Null, but not obvious how to go about it.


Finally - do not assume that accessing Null will lead to a crash. This is a debug feature only, in BlitzMax. BlitzMax's Null is not the same as hardware null, and accessing it does not cause a segfault the way it does in C or C++ - in release mode, reading from null will often silently succeed (the refcounting GC relies on this, technically making Null itself an instance of the Null Object Pattern in BlitzMax). You need to check for Null manually in BlitzMax if you want your code to be safe in release mode, or add "gates" that prevent Null values entering an area. Debug mode doesn't use hardware signals to check for Null - it just inserts an invisible If branch around every single use of an object variable.


Bobysait(Posted 2016) [#4]
Ok, then just declaring the array without initialization means an object is created.
Thanks for the confirmation.

That also explain why I couldn't understand the maxgui TGadgetItem creation
-> the "items:TGadgetItem[]" is never initialized with a new or auto-array form (I searched the sources so deeply that I felt I was beginning to think as a gadget ...), and I couldn't find why it doesn't crash here

Method InsertItem(index,text$,tip$,icon,extra:Object,flags)
?debug
		If index<0 Or index>items.length Throw "Gadget item index out of range."
?
		items=items[..items.length+1]


But then, it makes sens.



ps :
Actually I also realized I can push an object to a Null array on the fly
It's not really related to the topic (or maybe it is ... in some kind), but I'm still discovering stuff years after the beginning :)

Local t:Object[] = Null;
t :+ [Object(Null)]
print t.length



Brucey(Posted 2016) [#5]
declaring the array without initialization means an object is created.

No. Your variable just points to an address in memory which represents a global empty array.

Actually I also realized I can push an object to a Null array on the fly

That's not doing what you think. :+ on an array will allocate a New array of an increased size, copy the old contents to it, and add the new stuff at the end.


Bobysait(Posted 2016) [#6]

That's not doing what you think. :+ on an array will allocate a New array of an increased size, copy the old contents to it, and add the new stuff at the end.


Actually, it's exactly what I thought it does, but I didn't explained in the details cause I thought it would be hard for me to explain this in English.
But yeah, t :+ [Obj] means t = t[..size] + [Obj]
that 's why I said "It's not really related to the topic (or maybe it is ... in some kind)". Sorry for that, I'm not always very clear ^_^ (I'm pretty much more often obscure actually)