Very cool!!! Thanks…
Tims approach, in an effort to make a ‘constant’ array, is only allowing access to it’s elements. The downside is you don’t know how many elements there are and that’s the change I added.
If you use
Function ConstantArray as String()
static theArray() as String = Array("a", "b", "c")
return theArray()
End Function
that’s returning the array which can then be manipulated like any array, ie it’s not ‘constant’.
There’s no constant arrays in Xojo so you have some tradeoffs to consider…
- A method that remakes and returns a new array each time. Potential inefficiency.
- A method that makes a single Static array and returns that. Doesn’t adhere to being ‘constant’.
- A set of methods or a Class that models a constant array. More work to set up.
If you don’t need to preserve the constant aspect of the array, or you’re going to be careful and not modify it then use #2. But really this is the same as just making a globally array property.
If the array is short and not called upon all that often then #1 isn’t really that bad. Sure it’s being rebuilt each time but that’s pretty fast.
For #3 I’d make a class like this
[code]Class ConstantStringArray interfaces xojo.Core.Iterator, xojo.Core.Iterable
Private Property mItems() As String
Private Property mLast As Integer
Private Property mIterIndex As Integer
Private Sub Constructor(arr() As String)
mItems = makeCopy(arr)
mLast = arr.Ubound
End Sub
Function Operator_SubScript(index As integer) As String
return mItems(index)
End Function
Function Ubound() As integer
return mLast
End Function
Function duplicate() As String()
return makeCopy(mItems)
End Function
Private Function makeCopy(arr() As String) As String()
dim last As integer = arr.Ubound
dim r() As String
redim r(last)
for i As integer = 0 to last
r(i) = arr(i)
next
return r
End Function
Private Function GetIterator() As Xojo.Core.Iterator
// Part of the xojo.Core.Iterable interface.
mIterIndex = -1
return self
End Function
Private Function MoveNext() As Boolean
// Part of the xojo.Core.Iterator interface.
mIterIndex = mIterIndex + 1
return mIterIndex <= mLast
End Function
Private Function Value() As Auto
// Part of the xojo.Core.Iterator interface.
return mItems(mIterIndex)
End Function
End Class[/code]
usage
[code]dim MyStrings As new ConstantStringArray( Array(“a”, “b”, “c”) )
for i As integer = 0 to MyStrings.Ubound
MsgBox MyStrings(i)
next
for each s As String in MyStrings
MsgBox s
next[/code]
If you need to pass this someplace that requires String() then you have to call MyStrings.duplicate. I guess this could be done as an Operator_Convert though. This class is immutable but you could still accidentally replace the instance, so it’s not a perfect ‘Constant’.
There’s ways to hide the Constructor from this class but that’s a bit more involved and this was supposed to be simple. You could add an isInited boolean and raise an exception in the Constructor if called a second time.
If the array is short then #1 may actually be more efficient than a class. Needs testing. Which is more important, constancy or efficiency?
Thanks, as usual, Will. All I really needed was an array whose content remained static, that I could access via a few different methods. With Filemaker, I would do this by assign a global variable a string of carriage-return delimited values and be done with it. I was looking for something similar with Xojo. I figured with Xojo I could just use a global Property to do that, using a Method to set it. But then Tim reminded me that I could just use a Method without a sister Property, and have it return what I want. So now I have a Method simply returning the array I want. I now use that Method as my “array”. So tradeoff #2 of yours is working for me.