Hashtables

Greetings,

I am discovering the joy of hashtables, but something is on my mind.

Is there a way to instantiate / create a hashtable and instantly give it values ?

For example, when you want to make a second array based on a previous array, you can write array2 = new Array (array1);
Or when you want to create an array with already existing values, you write list = new Array (1, 10, 100);

I can’t manage to do the same with hashtables. Must I really write table = new Hashtable (); and give it values after that (table.Add ()) ?

i think so yes, look for the java or C# command ref.

Even in the examples, it first instantiates, then defines by code the content.

My main problem is that the content must be initialized by code (Awake or Start, then). When I worked with LUA, I remembered I could write something like that, upon declaring a variable :

var table = 
{
    "keyOne" = "valueOne",
    "keyTwo" = "valueTwo",
    ...
}

…script ? (Javascript)

I don’t want to look dumb, but I guess it can’t be helped : I don’t see how ref could help. From the old posts, I understood it is used with an argument of a function, and allow to pass the variable reference as the argument, instead of its value. I highly doubt it would help me in defining the content of a hashtable upon its creation.

After a little more testing (in the dark), I managed to write something :

public var table : Hashtable = new Hashtable ({"test" : "sop", "test2" : "soppy"});

function Start ()
{
	Debug.Log (table ["test"]);
	Debug.Log (table ["test2"]);
}

It seems to works…

That’s similar to the C# 3.0+ syntax for Dictionaries, so what you got is probably fine:

Dictionary<string, int> test = new Dictionary<string, int>() 
{ 
	{ "asdf", 1 }, 
	{ "zxcv", 2 },
	{ "qwerty", 3},
};

You’ll probably want to use a Dictionary instead of a Hashtable for type-safety. (though I don’t know how much that matters for a UnityScript version)

Well, the type-safety is a plus (as long as the guy writing has the type in mind, no problem should arise).

I tried to give it a try, but it is not getting somewhere.

http://rick.measham.id.au/javascript/hash.htm

public var table : Hash = new Hash
({
	"test" : "sop"
});

function Start ()
{
	Debug.Log (table ["test"]);
}

Error message :

Sigh…anyone have a good idea, please ? (I can still go on with Hashtable, but I would like to see the ending of this)

“Hash” is not a built in type for JavaScript (let alone UnityScript, which apparently is reserved by Boo). Plus it’s a pretty piss-poor name for a HashTable class (it’s a HashTable, not a Hash).

Try using System.Collections.HashTable instead. Or you can use the UnityScript “Hashtable”: Unity - Scripting API: Hashtable

Hashtables are built in to Unityscript.

Just do this:

And note that you don’t need to use Add() to add values.

You can assign values like so:

myhash["key"] = "value";

and retrieve values this way:

Debug.Log(myhash["key"]);

?

I think I wasn’t clear : I know now how to use a Hashtable (from the blind tests, and, from now, your advices ;)). I am now trying to make a Dictionary, like FizixMan suggested (to lock the types).

In UnityScript ! :smile:

If I recall correctly, since UnityScript (in version 2.6.x) doesn’t support generics, you might be out of luck.

Although… puts on his handy dandy reflection haxx0z00rz0r0z0x0rz0 cap brb

The chicken walks away, sadly.

No one loves him … even UnityScript. :frowning:

VICTORY

sort of

import System.Reflection;

function Start()
{

	var dictionaryType = System.Type.GetType("System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]");
	//shorter version should work fine as well
	//var dictionaryType = System.Type.GetType("System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Int32, mscorlib]]");
	var constructor = dictionaryType.GetConstructor(System.Type.EmptyTypes);
	var dynamicDictionary = constructor.Invoke(null);
	
	print("IS NULL: " + (dynamicDictionary == null));
	print("TYPE: " + dynamicDictionary.GetType().FullName);
	try
	{
	
		var addMethod = dictionaryType.GetMethod("Add");
		var arguments = new System.Object[2];
		arguments[0] = "asdf";
		arguments[1] = 1;
		addMethod.Invoke(dynamicDictionary, arguments);
		
		var countProperty = dictionaryType.GetProperty("Count");
		print("COUNT: " + countProperty.GetValue(dynamicDictionary, null));
	
		//all of the below caused unity to completely crash and burn, hard; try/catch had no effect
		//var count = dynamicDictionary.Count;
		//dynamicDictionary["asdf"] = 1;
		//dynamicDictionary.Add("asdf", 1);
		//dynamicDictionary.Add("qwerty", 2);
	
		//print("CHECK: " + dynamicDictionary.Count);
	}
	catch (ex)
	{
		print("ERROR: " + ex.Message + ", TRACE: " + ex.StackTrace);
	}
		
}

Bottom line: theoretically possible to write a UnityScript wrapper for generic dictionaries. However, performance will be abysmal with all the reflection hax. All members of the dictionary have to be accessed via reflection or Unity implodes. Furthermore, you pretty much lose the primary benefit anyway (type-safety code reusability through generics). For all the pain, better off to write a fixed-type wrapper around Hashtable, waiting for Unity 3, or switch to C#.

Maybe I don’t understand what you guys are trying to accomplish, but if you’re just trying to create a dictionary class with fixed types, you can create a class that inherits from Hashtable, and only accepts/returns values that are strings (or whatever type you wish).

I’ve done this before to create an iPhone friendly hashtable, otherwise you have to cast everything ‘as String’.

First, I was trying to make the Hashtable work, but FizixMan (always him) dangled the happiness before my eyes, and I was taken into the quest of grabbing it.

Of course you can always cheat with Unity, but I’d rather love to use built in solutions :wink: (simpler and cleaner)

:shock: gaping

The second. :smile:

I tried to have a look anyway. You look like you are trying to retrieve the constructor of a type (that can change, explaining the looseliness of the variables type), retrieve its Add function, and add by it some arguments.

Geh…

Yes and no …

Yes :smile:

It is so unreal I should keep that in mind, for later (?!) use. Thanks you all ! (a wink for FizixMan , heh ;))

Yeah, that’s pretty much the jist of it. It’s relatively safe to use reflection when you know your types aren’t going to change (like the built-in .NET types, such as Dictionary).

This grabs a reference to the generic Dictionary<string, int> (string keys, integer values) by using the string representation of its type name. It looks kind of funky but that’s how generics type strings are formed.

That looks for a parameterless constructor, then invokes it.

Then yeah, everything else you need to use reflection to grab the other methods and properties. If I try to use UnityScript’s dynamic lookup to access them (by just hitting up dynamicDictionary.Add(), dynamicDictionary.Count) I get an error with no message, then a second error that causes the Unity editor to crash and close.

It’s not type-safe at compile time because you could pass in an in compatible object (say, a boolean) via reflection, and have it throw a run-time error.

I’m 93.8% sure that I heard that Unity 3 gives UnityScript generics support. Hopefully that does comes to pass.

Yeah, as soon as I read this line, I knew it was over (for my brain)…

Out of the topic but isn’t it 8:30 AM at Canada ? You wake up early… :slight_smile:

Well… Canada spans 6 time zones… >.>

But yes, 8:30 here and liek… some of us have day jobs. :smile: normally up at 7, but this chicken is sick ;_;

All types have a string representation.
string = System.String
int = System.Int32 (32 because it’s a 32 bit integer)
HashTable = System.Collections.HashTable (at least in C#, not sure if the UnityScript one points to the same)

Generics just add a bit more information because for any given Dictionary, it has two more nested types (for key and value)

P.S. switch to C shaaaaaaaaaaaaarrrrrrrrp

:wink:

If I were to switch to C# now, I would have to rewrite all my currents scripts, which are written in UnityScript :smile: I don’t even want to think about it now.

After this project, maybe ?

Maybe…?

Maybe…?

Maybe…?