lizmat / Hash-Ordered

Role for ordered hashes
Artistic License 2.0
2 stars 3 forks source link

Hash::Ordered does not autovivify nested keys #2

Open MARTIMM opened 3 years ago

MARTIMM commented 3 years ago

in REPL it shows like

> my %m is Hash::Ordered
{}
> %m<a> = 10
10
> %m<b><a> = 10
Cannot modify an immutable Str (Nil)
  in block <unit> at <unknown file> line 1

I would like it to create key 'b' then 'a' then assign 10 not like following because it is cumbersome if it is very deep

> %m<b> = Hash::Ordered.new
{}
> %m<b><a> = 10
10
lizmat commented 3 years ago

Interesting... I would have to think about that. @japhb ideas?

japhb commented 3 years ago

(Updating this from off-ticket discussion ...)

@lizmat and I think it might be necessary to fix this in a general way for all modules based on Hash::Agnostic, but we haven't figured out exactly how yet.

MARTIMM commented 3 years ago

No hurry, I've decided to rewrite my own Ordered Hash version because there are some other problems I've encountered that are needed in BSON (where I needed it for) and cannot be provided by this module without losing its general purpose.

japhb commented 3 years ago

Oh? What else did you find missing? (If we're going to have to make general changes to the Hash::Agnostic family, it seems useful to have a good idea of where the gaps are right now.)

MARTIMM commented 3 years ago

These are not general changes I need, except for the autovivication mentioned for this issue. It is that BSON cannot describe certain constructs. I can trap those while traversing the structure throwing an error or converting them. For instance;

These are the most important things I want to implement.

japhb commented 3 years ago

Wow, that's quite restrictive. But fair enough.

I am curious about the restrictions on arrays (not being at the top level and not being nested). It's my understanding that an array is always represented as a document with stringified integer keys (which are completely ignored by the decoder, but oh well). Thus if someone had an array at an unexpected level, it would just be treated as a document instead, which seems somewhat annoying but otherwise harmless.

Or are you trying to ensure only accepting the subset of possible structures that would be guaranteed to roundtrip?

MARTIMM commented 3 years ago

True, an array is converted into a document but and array can only be a value of a pair. so the following [ :a<a>, :b<b>, [:c<c>]] must not happen. It must be something like :x([ :a<a>, :b<b>, :y([:c<c>])])

When you convert an array at the top, or elsewhere, to just a document, you cannot ever get an array back because the array is gone(converted).

MARTIMM commented 3 years ago

BSON was developed to be used with mongodb. That is the reason that all variables must have a name which can be searched for in the database. Take for example the array above [ :a<a>, :b<b>, [:c<c>]], it would be difficult to search for [:c<c>]. or worse, to search it from [ :a<a>, [:b<b>, [:c<c>]], [:c<c>]], Perfectly legal for Raku but not easy to find it back from a database if it would be acceptable.

MARTIMM commented 3 years ago

@japhb, I think that I have made an error, (more than one!) :-( Studying the BSON spec again I can now see that arrays can be nested. Any BSON type can be used as its content. I do not know how to handle Pair types in an Array except to convert them to a one element List of Pair. So, doc => [ 1, 2, 3, :a<a>, :b<b>, [:c<c>]] would become something like doc => [ 1, 2, 3, (:a<a>), (:b<b>), [ (:c<c>) ] ]. When encoding the lot, the document 'doc' would have an array with two nested documents and a nested array, also with a document.

Sorry for any confusion caused by me. If you would like to mail about it, you may use mt1957@gmail.com. Maybe there are other things I have not understood.

@lizmat Sorry for polluting your issue with matters not related to the issue.

Regards Marcel

lizmat commented 3 years ago

@MARTIMM no worries :-)