NILing an array

I was looking through some code I wrote last week.
At one point I am assigning an array which is stored on an object into an array property of a different object from a different class.

While i need to keep both objects around, I only need to keep the the second array reference around for a little while and when I’m done with it, need to get rid of it without affecting the array on the 1st object .

Without thinking I treated the array as I would an object and did:

Object2.theArray = NIL

Instead of
Dim EmptyArray() as ArrayType
Object2.theArray = EmptyArray

The compiler did not complain and it seems to work (at least in the current Xojo version - I will also need to compile in an older version to support 10.6).

Are we supposed to be able to NIL arrays? Is it supported? If so has it always been supported? Is there any downside to NILing it vs assigning a new empty array?

Thanks,

  • Karen

you can set it to nil. Arrays are just special objects.

While setting an array to nil is valid, I never do that because, the way I write my code, I never expect an array reference to be nil and would generate exceptions if I took up that practice. I would have gone with some variation of your second option.

ReDim Object2.theArray(-1)

Not an option. Since Object2 and Object1 point to the same array, she should lose it in both objects.

Yes, of course.

The docs mention that Nil can be assigned to an array:

Interesting:

Dim arr() As String Break // shows String(-1) in the debugger arr = Nil Break // shows Nil in the debugger

EmptyArray() ? nil reference to an array

This is analogous to “” and NULL in a database

Nil is “no value assigned of ANY kind”
Array() is “empty array”

I didn’t say it was wrong, only that it is interesting that

Dim arr() As String

is not Nil, which it maybe should be, because there is no assignment.

[quote=161933:@Eli Ott]Beginning with version 2006 Release 4, Nil is a constant of its own datatype, not an Object. It can convert itself to any object class, any array type, or any of the pointer types (Ptr, WindowPtr, CString, PString, WString, and CFStringRef).
[/quote]

I never noticed that in the Docs (Probably because i started with RB long before that) … I always thought NIL was only for objects.

That said IMO there should be no such thing as a NIL array… It is counter intuitive (at least for us older folks who don’t think of Arrays as objects) and as Kem noted for a NIL array if you did

ReDIm NILArray(5)
or even
ReDIm NILArray(-1)

You would likely get a Nil object exception, which is REALY REALLY unintuitive and bug prone!

IMO Arrays (or at least their API facing us regardless of what is under the hood) should either fully BE objects requiring NEW or not behave like objects at all.

  • Karen

Nobody thinks of Xojo arrays as Object, they are pointers - and as the docs say, Nil is not an Object anymore but its own datatype and can be used for any non-scalar datatype (Object, arrays, Ptr, WindowPtr, CString, …).

Well maybe in C based languages.

A pointer does nor allocate (or deallocate) memory… It knows nothing of size. We also can not allocate a bock of memory AS raw memory and assign that address to an array.

And Array does know how much memory it as and can interpret the data in it only one way. I always thought of it as a data structure that under the hood uses pointers based on the indices passed… but with no direct external access to the pointer itself or the memory it points to… That is what MemoryBlocks are for.

Again the real issue is that once an Assay is NILed you can’t just ReDIM or even call UBound on it.

This makes the behavior of arrays neither fish note fowl and therefore unintuitive when NIL.

I’m not advocating that Arrays be objects. just that they not be allowed to be NIL.

  • Karen

There is one very convenient use for this, and I wouldn’t want to lose the option. You can define a method like this:

Sub MyMethod (arr() As Something = nil)

This lets you tell the difference between a given empty array and no array given.

[quote=161954:@Kem Tekinay]There is one very convenient use for this, and I wouldn’t want to lose the option. You can define a method like this:

Sub MyMethod (arr() As Something = nil)
This lets you tell the difference between a given empty array and no array given.[/quote]

Never thought of that…

For that reason it would nice to be able to assign and test for NIL for EVERY datatype. I most often come up against that for colors where all values make sense… I hate having to have a separate boolean to go along with a color.

  • Karen

I created classes for this like StringParam, BooleanParam, etc. I don’t think I did ColorParam, but that’s possible too. Using Operator_Convert, it’s easy enough to go back and forth with whatever the value is supposed to represent, and you can test for nil.

Your method would be defined something like:

Sub MyMethod (c As ColorParam = nil)
  dim theColor as Color
  if not ( c is nil ) then
    theColor = c
  else
    theColor = defaultColor
  end if

I haven’t looked but this is supposed to be part of the new framework eventually too.

[quote=161938:@Eli Ott]I didn’t say it was wrong, only that it is interesting that

Dim arr() As String

is not Nil, which it maybe should be, because there is no assignment.[/quote]
That defines an array that has no members like always as if you had written dim arr(-1) as string

Being able to set an array to NIL and test is is newer than that syntax
Changing it so that style assigned nil would break untold amounts of code

Certain types are values types not reference types
Color, integers, etc and there’s no opportunity to set them nil or test them for nil as theres no references involved
Now we COULD make EVERYTHing a reference type so you can test for nil on anything but I think people would be very upset with the commensurate hits since EVERY access would need to go through a pointer and this would probably hurt performance.

And every type would now be “ptr + space for the type” so things like integers which are now 32 bits would double in size.

I really don’t think you’d like it

[quote=162029:@Norman Palardy]Certain types are values types not reference types
[/quote]

I know and understand what you are saying…

[quote]Color, integers, etc and there’s no opportunity to set them nil or test them for nil as theres no references involved
[/quote]

That is a nice thing about passing a variant parameter… they CAN be NIL … but they cost in terms of memory, execution speed and loss of type checking.

I know but I often lament not having a “no value passed” default value for things like colors (with Numbers there often is a value that does not makes sense, and I use that)… I figure you guys could figure out some magic to deal with this that won’t cost anything! :wink:

For colors sometimes i define an “illegal” color that is unlikely to be really passed such as $c000100FF as the default, but it feels like a kludge.

  • Karen

Every color, integer etc is a “legal” value - although it ay be unlikely in YOUR app
There really is no way for us to decide that there is a flag value that would work for everyone in every situation
Its a 100% certainty that IF we decided on such a value someone would report a bug about this value

It is
Its only illegal in your context - someone else might look at that & say “gee thats a perfectly fin color value”

Java has int and Integer - one a value type & one a Class based type you can instantiate by passing an int
They do this for all the basic type they support - there’s a value type based one & a class based one but quite honestly it confuses the heck out of most folks when they see it for the first time.
And there are most definitely implications as far as runtime & memory go.

You can make a Class that converts from color to test for nil. Though when I’ve run into this issue before I’d overload and call one from the other instead of trying to use optionals/defaults.

[code]Class CColor

c As Color

Sub Operator_Convert(rhs As Color)
c = rhs
End Sub

End Class

Sub test(c As CColor = nil)
if c is nil then
MsgBox “nil”
else
MsgBox "red " + Str(c.c.Red)
end
End Sub

test(RGB(33, 0, 0))
test(&cFF0000)
test()[/code]

Thats basically the approach Java has taken
A class that boxes certain primitive types like int, boolean , double etc