Change value of string in a list?

BlitzMax Forums/BlitzMax Programming/Change value of string in a list?

I can read through a list and cast to whatever I need and change values of other objects, but for some reason I can not change the value of regular string variables in a list:
SuperStrict
Type TTest
	Field str:String
	Field a:Int
End Type

Local obj:TTest = New TTest
Local list:TList = New TList
Local myname:String = "Russell"

list.AddLast(obj)
list.AddLast(myname)

For Local a:Object = EachIn list
	Local temptest:TTest
	Local tempstring:String
	If TTest(a)
		temptest = TTest(a)
		temptest.str = "Goodbye"' THIS WORKS
		temptest.a = 10         ' THIS WORKS TOO
	ElseIf String(a)
		tempstring = String(a)
		tempstring = "Jones"	' WHY DOESN'T THIS WORK?
	EndIf
Next

I have tried various other methods and none of them change the value of the string.

Thanks in advance
Russell

Works for me but then you don't exactly say what's wrong.

If you then go through the list you'll see that the string still equals "Russell", not "Jones" as it should be:
For Local a:Object = EachIn list
	Local temptest:TTest
	Local tempstring:String
	If TTest(a)
		temptest = TTest(a)
		Print temptest.str ' Print correctly
		Print temptest.a   ' Prints correctly
	ElseIf String(a)
		tempstring = String(a)
		Print tempstring  ' Prints "Russell" instead of "Jones"
	EndIf
Next

What code are you using to view the list after it is modified?

Russell

All you're doing there is changing the local string, it shouldn't change the value of the completely different string in the list.

for example...
local a:int=10
local b:int=0
b=a
b=10

would you expect the value of 'a' to be 10? no ;)

What I want to be able to do is add various kinds of objects, including strings, to a linked list and then to be able to modify those objects within the list. I modified the TTest object's fields with no problem and it worked exactly as expected, but how do I do the same for the string object that was added?

I see what you mean as far as changing the local string, but it actually does change the value of the first list object's fields. Run this and you'll see that the two fields of the obj:TTest object are actually changed:
SuperStrict
Type TTest
	Field str:String
	Field a:Int
End Type

Local obj:TTest = New TTest
Local list:TList = New TList
Local myname:String = "Russell"

list.AddLast(obj)
list.AddLast(myname)

For Local a:Object = EachIn list
	Local temptest:TTest
	Local tempstring:String
	If TTest(a)
		temptest = TTest(a)
		temptest.str = "Goodbye"' THIS WORKS
		temptest.a = 10         ' THIS WORKS TOO
	ElseIf String(a)
		tempstring = String(a)
		tempstring = "Jones"	' WHY DOESN'T THIS WORK?
	EndIf
Next

For Local a:Object = EachIn list
	Local temptest:TTest
	Local tempstring:String
	If TTest(a)
		temptest = TTest(a)
		Print temptest.str ' Print "Goodbye" : correct
		Print temptest.a   ' Prints 10 : correct
	ElseIf String(a)
		tempstring = String(a)
		Print tempstring  ' Prints original value "Russell" instead of "Jones"
	EndIf
Next

Any ideas on how to change the string object as well?

Russell

For Local a:Object = EachIn list
	Local temptest:TTest
	If TTest(a)
		temptest = TTest(a)
		temptest.str = "Goodbye"' THIS WORKS
		temptest.a = 10         ' THIS WORKS TOO
	ElseIf String(a)
		TLink(list.findlink(a))._value = "Jones"
	EndIf
Next

Maybe not the fastest of solutions, but I can't think of any other way of doing it.

Thanks REDI, at least there IS a way to do it! There MUST be a more efficient way, though.

Mark? Brucey? Anyone?

Russell

Local list:TList = New TList

For Local i:Int = 1 To 10
	list.addLast("test"+i)
Next

Local enum:TListEnum = list.ObjectEnumerator()

While enum.hasNext()
	Local link:TLink = enum._link	
	If String( link._value ) = "test4" Then link._value = "I've changed!"
	enum.NextObject()
Wend

For Local s2:String = EachIn list
	Print s2
Next


There MUST be a more efficient way, though.
Either wrap the string in a type or collect your objects within a TMap.

@Sledge: Yeah, I thought of that one too (and it works). But I just can't believe that a little 'ol string value can't be changed more efficiently/easily.

@Perturbio: Thanks...But YIKES! :)

Russell

@Perturbio: Thanks...But YIKES! :)


I think that's as good as its going to get.

@Perturbio: Thanks...But YIKES! :)


It isn't really a big step away from using Eachin, you're simply using the same methods it uses but now have access to the link, ideally though, the list would expose the current link in it's enumerator so that you could do something like:

For Local o:Object = EachIn list

	if string(o) then list.enumerator.currentLink then
		list.enumerator.currentLink.value = "changed value"
	EndIf

Next


(The above code would obviously have some issues (i.e. nested EachIn would need more work since the enumerator in this instance would be overwritten)).

maybe if you had some way to get the enumerator for the current EachIn scope?:

For Local o:Object = EachIn list
	Local enum:TListEnum = getEachInEnum()
	if string(o) then enum then
		enum.currentLink.value = "changed value"
	EndIf
Next


What I'm wondering is: If a string is an object, doesn't that object have a field (or method to access that field) that actually stores the value for the string?

It's no big deal, really. I was just exploring linked lists and trying some things out and found it weird that it wasn't straightforward. I seem to remember that on the old Blitz Basic 2 (for the Amiga), that linked lists worked on the idea of a "current" link that BB kept track of (no TLinks, etc to be aware of) and that you could access it easily and modify the contents. It's been so long, though, that I don't remember the syntax or even how it worked completely.

Anyway, thanks everyone.

Russell

What I'm wondering is: If a string is an object, doesn't that object have a field (or method to access that field) that actually stores the value for the string?


BlitzMax strings are immutable (as in many languages). However, if you don't change the length you *could* write over the memory, but then any copies of that string would also change... Not a good idea.

I would just use Remove and Add-methods - the performance effect won't be too much unless you are doing something extreme, in which case Perturbio's code is the way to go.

Thanks, everyone.

Russell