Structures as DictionaryKeys?

Maybe I am missing some stupid mistake in my code…

I thought a Variant could be anything , yet when I try to use a structure variable as a dictionary key I get a TypeMismatchException on this line:

[quote]If Cmpd.RI_Data.HasKey(DataType) then
[/quote]

Where DataType is a variable of type RI_Info.TypeStruct which is defined as:

Structure TypeStruct ColumnType As ColumnEnum RampType As RampEnum CalculationType as CalculationEnum End Structure

Where all the Enums are defined as In64 as they are stored individually as integers in an SQLite DB and IIRC SQLite only does Int64 (I know datatypes are not enforced in SQLite but I want to be consistent)

(BTW the Navigator shows the Enums as Integers not Int64s… it’s only in the inspector that one sees that the enum is an Int64 … is that a bug?)

So can dictionary keys not be structure variables, or am I doing something wrong or missing something obvious and being stupid?

And If I can’t use structure variable as keys is that a bug?

I could use Structure.StringValue as workaround (maybe stetting the String encoding to NIL to deal with case sensitivity) Or Structure.ByteValue (never tried using an array as a dictionary key… would that work?)…

I can certainly think of other workarounds but its seems to me none should not be needed!

Thanks

  • karen

I had an issue with Dictionary keys a few years ago… Trying to use a PAIR as the key… if I recall.
it didn’t work well, and Norman explained why… don’t recall the reason , but the conversation can be found in this forum someplace

[quote=411812:@Dave S]I had an issue with Dictionary keys a few years ago… Trying to use a PAIR as the key… if I recall.
it didn’t work well, and Norman explained why… don’t recall the reason , but the conversation can be found in this forum someplace[/quote]

i think I remember that… a Pair is a class and IIRC I think it used the class instance address and I understand why that should not work all the time…

But a Structure is not a class so is always passed ByValve by default (unlike a class instance as that has no built in serialization) so i think it SHOULD work as it should be just using a hash of raw bytes of the structure as the key under the hood…

Yes one would lose the link to the specific enum definition, but for dictionary key that being a problem in actual use is so highly unlikely as not to be worried about IMO…

But if it is a major concern, an internal unique link of a set length to the specific structure type could be added to the byte list before the hash is created for structures. That way ONLY the byte pattern originating from those type of structs would match.

So in any case it COULD be made to work…

If Xojo inc thinks it should not, then this needs to be explained in the language reference… saying that the key is a Variant implies it should work for structure variables, even to someone with enough sophistication to realize why it would not work for class instances with identical properties…

It would also not hurt to mention the issues with class instances as keys as well in the docs.

  • karen

while from one point of view that is “true”, I think from a technical point of view it is more like a class without methods
but that is just MY “point of view” :slight_smile:

[quote=411816:@Dave S]while from one point of view that is “true”, I think from a technical point of view it is more like a class without methods
but that is just MY “point of view” :)[/quote]

Well that may or may not be true… but that is an implementation detail that should not affect usage of structures as dictionary keys… after all how often have we been told that we should not concern ourselves with implementation details!!!

In any case, I would say If classes had built in serialization, then dictionary keys should work for class instances as well!!! But of course there is not, so i don’t expect that…

As I said this should either be made to work (and that IMO is what should be done) or the documentation updated to state it does not …

Over the years the things that have bothered me most about Xojo/RS/RB were things that logically SHOULD work (particularly as documented), but do not… It causes me to waste my time and kills productivity even if easily worked around in the end.

  • karen

It is easy to write a general method to produce a safe dictionary key, that will work for all structures without the code needing to know the Structure details…

But Ideally I would like it as an extends method that will work for all structures (and not have to define one for each structure definition)… Is it possible to do that? There are methods that work like extends methods for all structures in the framework (StingValue, ByteValue, Size), so maybe it is possible? If so, how?

Alternative I could write a method that uses a variant parameter… but then it might get called on non structures and I don’t get autocomplete on structures to remind me to use it…

  • Karen

The TypeMismatchException indicates that a structure cannot be used as a dictionary key. The documentation hints at it, but isn’t explicit. It would be nice if a) the documentation for Dictionary mentioned this, and b) they used a more descriptive exception like UnsupportedValueException. Although, the use case is rare enough that creating an exception just for it is probably overkill, so I’ll give them TypeMismatchException.

I imagine it wouldn’t be too hard to hash the contents of a structure and thus use it as a dictionary key, so there might be some hope for a feature request.

You can write an extends method for a particular structure, but not a generic one that extends Structure itself. I guess the concept of Structure is too high level? Structures are a weird hybrid. They’re very good for their intended purpose, but not really suited as a generic variable type.

Structures seem to be another partially implemented/supported feature compared to other languages.

I use them for things besides declares because they autocomplete their members and I can define them within a class (which I can not do for class - and yes I know how to use a module to keep helper classes private… but more complexity and configuration that way).

I often use structures for logical groups of simple datatypes. That helps organize a class with a lot of properties, and make the autocomplete list for the class shorter, and more intuitive and so easier to use… and can make code more readable without being significantly less explicit IMO.

I wish they were promoted to full datatypes!!!

  • karen

The problem is that a Structure is not a datatype. It is a mechanism for defining datatypes. And that causes some discontinuity with other things that are datatypes. But I feel your pain.

@Karen Atkocius — I’m curious… let’s say that dictionaries did support structures as keys for a moment. How would you expect the key lookup to work?

I gave an overview above but thinking about it here is more detail… The specifics could be done may different ways and there may be better ways than I can think of (I am a “citizen developer” with no formal training (Well unless you consider teh intro Fortran course I took in teh 1970s!)

That said, to me it seems straightforward given I don’t know how things are done under the hood.

The easiest way would probably be using a fixed length hash (independent of structure size) of the raw bytes of the structure as the key under the hood…

Yes one would lose the link to the specific enum definition, but for a dictionary key that being a problem in actual use is unlikely enough as not to be worried about it IMO…

But if it is a major concern, an internal unique link of a set length to the specific structure type (Some sort of serial number that IDs the structure definition uniquely),could be could be appended to the hash of the underlying bytes . That way ONLY the byte patterns originating from that structure definition would match.

Probably not needed but that type of approach could be used for all datatypes if one needs to match not only the underlying byte representation of the data but also teh datatype… In that case maybe a boolean parameter on the dictionary constructor could turn that feature on for that instance if desired would be a good idea…

Being able to set datatype specificity is probably overkill, but it could be useful for some… It’s just a logical extension of dictionary capabilities.

In any case logically one would expect structures to be used a dictionary keys as they are not classes …In general I would like structures to be seen a first class datatypes… they can be very helpful for organizing properties in classes (as they can be defined within a class) and make autocomplete lists more manageable.

  • Karen

One might also argue that the key should be the Ptr to the structure, making all instances of the structure unique.

What you could do is create a wrapper for Dictionary which takes your structure as a parameter to your own Value method, does the hashing for you and then stores the value into the embedded dictionary.

[quote=411890:@Greg O’Lone]One might also argue that the key should be the Ptr to the structure, making all instances of the structure unique.

What you could do is create a wrapper for Dictionary which takes your structure as a parameter to your own Value method, does the hashing for you and then stores the value into the embedded dictionary.[/quote]

That. Would make it not useful for me…anda bx unexpected for a datatupe that is passed byzalue. I would call such behavior a. Bug

What I was trying to point out is that because structures can contain other data types, the “value” could be interpreted more than one way. While it being a ptr wouldn’t be useful to you, it might be to someone else.

I’d say that if you want to use a hash of the bytes of memory that a structure represents, then that’s what you should pass in, and not the Ptr itself.

[quote=411895:@Greg O’Lone]What I was trying to point out is that because structures can contain other data types, the “value” could be interpreted more than one way. While it being a ptr wouldn’t be useful to you, it might be to someone else.

I’d say that if you want to use a hash of the bytes of memory that a structure represents, then that’s what you should pass in, and not the Ptr itself.[/quote]
I do not see how passing. A pointer for a data type would be useful… It is not a class and that would not be consistent with how the frameworks treats them for us passing a by value by default
The key difference (at the appropriate level of abstraction for a high level language) between a datatype and a class ls that datattypes are passed by value)

If I want to use an address instead of the actual data l would (could) use a class.

That said a method that autocompletes for all stuctures like stringvalue that returns an appropriate hash for a dictionary key would be a decent compromise

If I wanted to deal with things like byte hashes for dictionary keys I would be using C

Sorry for the noise. I was trying to offer alternatives which would work in Xojo.

Greg,

I can figure way to get it to work… but not intuitively, conveniently and transparently… and that is why I use Xojo over C…

If you were just suggesting workarounds… thank you…

In my code for this specific instance I created a workaround… but I would like to see an inuative general transparent solution…

Dictionary keys CAN be made to be created from the bytes that make up the structure data in Xojo if xojo Inc decides to do it… and that is the intuitive thing one would expect from how structure behave in other places in the framework…

I though you were arguing that it SHOULD be based on the address… If so I disagree strongly and I think for good practical and philosophical reasons … This started to feel like the new vs old framework arguments - differences in basic philosophy like those.

In general i think Structures could be much more useful and powerful if the framework really respected them as datatypes for general use than just something for use with declares… Xojo is half way there… It would be a benefit for the language to move farther in direction IMO…

  • karen

BTW how I am using the structure at the top of this thread is getting data from various sites on teh web and aggregating.grouping them based go teh the values of those 3 parameters and using them a dictionary to do it…

It is analogous to using a multi column key or index in a database table. That is why I need the dictionary key to be based on the underlying data and not the address. The values are contained on the fly with each search and may or may not already be in the dictionary… a pointer address would be well pointless for that case!

  • Karen

why not forgo a “dictionary” and use a SQLite table (in-memory?) instead.
This removes the need for a “structure” as each value would be a field
This allows the “record” to be found by any field or combination of fields