New variable from variable

BlitzMax Forums/BlitzMax Programming/New variable from variable

Brucey(Posted 2014) [#1]
It was just pointed out to me that BlitzMax accepts the following as valid (and it actually works) :
    function cloneObject:object(obj:object)
        'create a new instance of the objects type
        Local clone:object = New obj
    end function


I always thought the bit after "New" had to be an actual Type, rather than an instance of one.

Is this an undocumented "feature", or a bug?


Yasha(Posted 2014) [#2]
This isn't really the kind of thing you can add to a language "by accident"...

It's a great, practical feature. Even aside from the many legitimate uses of it as-is, imagine what you can do with it when combined with e.g. dynamic class generation.

I think this kind of little touch is what really adds to the language's character.


Derron(Posted 2014) [#3]
Sounds I have mailed you a bcc-ng-bug instead of a bcc-bug. Sorry pal :p.

Even if this is a "bug" - I do not see a reason for not including it in bcc-ng too (is there a "disadadvantage" of this behaviour?).


bye
Ron


GW(Posted 2014) [#4]
I admit, that is handy in certain limited cases.
But, I've never encountered a need for that in the wild. If 'Brucey-max™' didn't support that kind of thing I wouldn't be concerned either.
I agree a bit with Yasha though, it a slick feature


Derron(Posted 2014) [#5]
It was used 5 years ago in :

posts.php?topic=83004

http://www.blitzbasic.com/codearcs/codearcs.php?code=2132

To make it compile using BCC-NG I replaced

(obj = param "obj:object" of a function)
local clone:object = new obj

with

local objTypeID:TTypeID = TTypeID.ForObject(obj)
local clone:object = objTypeID.NewObject(obj)

bye
Ron


Azathoth(Posted 2014) [#6]
If I recall correctly, Mark said it was a feature but wasn't sure if he should remove it because it might cause confusion.


GfK(Posted 2014) [#7]
You have GOT to be sh*tting me??

The times I've spent writing functions to clone objects and I could have done it this way all along??!!? >:|

I'm going to find a small man to have a fight with. :/


Brucey(Posted 2014) [#8]
The times I've spent writing functions to clone objects...

Don't worry, it doesn't actually clone anything. Your time was not misspent :-p

The important bit is this :
New obj

which creates a new Object of the type of whatever the variable "obj" is.


Azathoth(Posted 2014) [#9]
clone:object = New obj

Doesn't actually clone 'obj' but rather creates a new instance of obj's Type. For example if 'obj' is a TList (even if cast to Object) 'clone' will be a new TList, the data isn't copied.

Edit: Just remembered arrays don't work.


GfK(Posted 2014) [#10]
which creates a new Object of the type of whatever the variable "obj" is.
Ah... I see. Using the word "clone", I assumed that you meant this was some undiscovered magical way of cloning an object.

I'd better go and apologize to Ronnie Corbett.


Derron(Posted 2014) [#11]
Yeah "new whateverobject" creating a clone would be a big portion of "automagicalness".

Think the compiler cannot know what the dev means with "clone".

While "cloning" strings/ints means "copying" them, this is not valid for objects. So Azathoth's clone function only "copies" basics like strings/ints. Arrays get handled separately but for more complex types it just uses the "reference" (which is what "TField.Get(object)" will do - it returns a string of whatever fieldtype you request).
To "deep clone" you should know what is constructed in which way.

Eg. I added

		'=== LISTS ===
		If objTypeID.ExtendsType(ListTypeID)
			local list:TList = CreateList()
			For local entry:object = EachIn TList(obj)
				list.AddLast( CloneObject(entry) )
			Next
			return list
		EndIf

		
		'=== TMAPS ===
		If objTypeID.ExtendsType(MapTypeID)
			local map:TMap = CreateMap()
			For local key:string = EachIn TMap(obj).Keys()
				map.Insert(key, CloneObject(TMap(obj).ValueForKey(key)) )
			Next
			return map
		EndIf	


to Azathoths code - but as soon as a field contains a type extended from TList, you cannot guarantee that it still works that way.
One option would be to check for a helper method in each type ("CreateClone(original:object)") which you then run when cloning instead of using the generic approach. So if you override a TList/TMap you then would define such an helper, this helper is then doing more specific things etc.

Without this you will run into trouble as objects might share things (same reference).


bye
Ron