I have a bunch of constants defined as strings in a module.
Apple = “Apple”
Banana = “Banana”
Cantaloupe = “Cantaloupe”
I want to make an array that is immutable called fruit
Fruit = {Apple, Banana, Cantaloupe}
How do I define the Fruit array?
I have a bunch of constants defined as strings in a module.
Apple = “Apple”
Banana = “Banana”
Cantaloupe = “Cantaloupe”
I want to make an array that is immutable called fruit
Fruit = {Apple, Banana, Cantaloupe}
How do I define the Fruit array?
You can’t in the strict sense of your question. The closest you can come is to create a method that returns a string array, something like this:
Function FruitArray () As String()
return array( Apple, Banana, Cantaloupe )
End Function
But nothing will stop you from doing this:
dim arr() as string = FruitArray
arr.Append "Anvil"
But at least FruitArray will be the same the next time it is accessed directly.
You could create a custom class that behaves like a string array but has no Append method as well.
If you code this as a class or a method how does this for loop behave?
for f as string in m.FruitArray
...
next
Is this going to reconstruct FruitArray on every iteration of the for loop?
Theoretically if FuitArray isn’t a constant but is a method or a mutable array, then the contents and size of the array can change between iterations of the for loop. I mean we code to avoid these things and we know that we won’t change them, but the language isn’t giving me an immutable constant array.
dim a(-1) as string = m.FruitArray // is this a bunch of string copies?
for f in a
...
next
This seems safer but… is the contents of the array duplicated because we are talking about string objects. i.e. not really fast or optimal.
You can add the Iterable interface for for-each loops. http://developer.xojo.com/xojo-core-iterable
See my attempt at a constant string class here… https://forum.xojo.com/conversation/post/262227
[quote=269122:@Will Shank]You can add the Iterable interface for for-each loops. http://developer.xojo.com/xojo-core-iterable
See my attempt at a constant string class here… https://forum.xojo.com/conversation/post/262227[/quote]
I didn’t see your post the first time around. Your class should only implement Iterable and have a separate iterator class.
No.
Yes.
One clarification here:
dim s1 as string = "hi"
dim s2 as string = s1
dim s3 as string = s1
That code has created one string with three references to it. The string was not copied.
Why a separate class? Would a separate instance be enough for whatever the issue is?
[quote=269126:@Kem Tekinay]One clarification here:
dim s1 as string = "hi"
dim s2 as string = s1
dim s3 as string = s1
That code has created one string with three references to it. The string was not copied.[/quote]
True, but
dim a1() as string = m.FruitArray
dim a2() as string = m.FruitArray
dim a3() as string = m.FruitArray
could, assuming the correct implementation of FruitArray, yield 3 copies of the strings.
But string isn’t a class it’s a type. Doesn’t that matter?
dim i1 as integer = 1
dim i2 as integer = i1
modifying i2 doesn’t change i1.
[code]Module FruitModule
Private Function GetFruitInstance() As Fruit
Static ti As Introspection.TypeInfo = GetTypeInfo(Fruit)
Static cis() As Introspection.ConstructorInfo = ti.GetConstructors()
Static ci As Introspection.ConstructorInfo = cis(0)
Static f As Fruit = ci.Invoke()
Return f
End Function
Global Function Fruit() As Fruit
Return GetFruitInstance()
End Function
Global Function Fruit(index As Integer) As String
Static f As Fruit = GetFruitInstance()
Return f(index)
End Function
Global Class Fruit
Implements xojo.Core.Iterable
Protected Sub Constructor()
// Fruit cannot be instantiated from outside this module
End Sub
Function GetIterator() As Xojo.Core.Iterator
Return New FruitIterator(Self)
End Function
Function Operator_Subscript(index As Integer) As String
Static items() As String = Elements
Return items(index)
End Function
Protected Shared Function Elements() As String()
Return Array(“Apple”, “Banana”, “Cantaloupe”)
End Function
Shared Function IndexOf(item As String) As Integer
Return Elements.IndexOf(item)
End Function
Shared Function Ubound() As Integer
Return Elements.Ubound
End Function
End Class
Private Class FruitIterator
Implements xojo.Core.Iterator
Private Dim mElements As Fruit
Private Dim mIndex As Integer = -1
Sub Constructor(elements As Fruit)
mElements = elements
End Sub
Private Function MoveNext() As Boolean
If mIndex >= mElements.Ubound Then
Return False
Else
mIndex = mIndex + 1
Return True
End
End Function
Private Function Value() As Auto
Return mElements(mIndex)
End Function
End Class
End Module[/code]
[code]// Get an item by index
Dim item1 As String = Fruit(1)
System.DebugLog item1
// Get upper bound
Dim ub As Integer = Fruit.Ubound
System.DebugLog Str(ub)
// Get the index of an item
Dim index As Integer = Fruit.IndexOf(“Banana”)
System.DebugLog Str(index)
// For loop
For i As Integer = 0 To Fruit.Ubound
System.DebugLog Fruit(i)
Next
// For Each loop
For Each item As Auto In Fruit
System.DebugLog CType(item, String)
Next[/code]
[quote=269138:@Brian O’Brien]But string isn’t a class it’s a type. Doesn’t that matter?
dim i1 as integer = 1
dim i2 as integer = i1
modifying i2 doesn’t change i1.[/quote]
Strings are immutable. So they don’t have to be copied until you modify one.
dim s1 as string = "abc"
dim s2 as string = s1
// you have a single string with 2 references
s2 = s2 + "d"
// now you have 2 separate strings
Strings act like the integers in your example, but as an implementation detail, they try to conserve space by not making an extra copy if they don’t have to. They’re an intrinsic type, but they have some characteristics of a class.
[quote=269119:@Brian O’Brien]If you code this as a class or a method how does this for loop behave?
for f as string in m.FruitArray
...
next
Is this going to reconstruct FruitArray on every iteration of the for loop?[/quote]
‘m.FruitArray’ will only be evaluated once, at the beginning of the loop.
If ‘FruitArray’ were implemented as in Kem’s first post, there’s no need to worry about this.
You can have multiple iterators created from the same iterable. Returning the same object from GetIterator causes moving one iterator forward to affect the ‘other’ ones.
[quote=269137:@Tim Hare]True, but
dim a1() as string = m.FruitArray
dim a2() as string = m.FruitArray
dim a3() as string = m.FruitArray
could, assuming the correct implementation of FruitArray, yield 3 copies of the strings.[/quote]
That would create three distinct arrays, but the strings within each would be the same, that is, not copies. In this respect, Strings behave much like objects.
@Eli Ott Thanks. That was a lot of work. Love that username
Et all thank you too.
hmm…
had a thought…
private const pseudoArray="A,B,C"
Sub Operator Subscript(index as integer)
return Split(pseudoArray, ",")(index)
End
[quote=269216:@Brian O’Brien]hmm…
had a thought…
private const pseudoArray="A,B,C"
Sub Operator Subscript(index as integer)
return Split(pseudoArray, ",")(index)
End
[/quote]
This has a much higher performance cost than returning the result of the Array() operator.
By golly, you’re right. I thought I had tested that out before, but I just ran some tests and it does appear that the framework is smart enough to reuse the string literals.