Re: "dumping" a map
- Posted by ghaberek (admin) Feb 17, 2023
- 1932 views
I'm new to OE and learning the ropes as it were. I've written a few simple programs, and I'm now exploring maps, which I want to use ultimately for a largish personal project that I have.
So, in my tests I want to be able to dump a text representation of a complex map, which includes nested maps, and none of the map functions in section 8.32 of the manual allow me to do this. I therefore would like to write a function that reads all key/value pairs in order to display them on screen, and calls itself recursively if a value is a nested map, but I don't know how to check if a value is a map. Using the map() function returns 1 for integers too, so doesn't help me.
Can anyone point me in the right direction, either to a function that already does what I want, or to tell me how to check if a value is a map or not ?
There's a lot going on here so I'll break it down topic by topic.
User defined types: Euphoria (currently) lacks any actual named-typing mechanism. The type syntax creates a user-defined type which is simply a function that 1) requires the base type specified in its parameter and 2) either passes or fails the type-check based on the output of the function (0 fails, anything else passes). When you declare a variable with a user-defined type (or UDT) it's still just an object and when type_check is enabled (which is on by default, use without type_check to disable it) the interpreter emits "type check" operations after every variable assignment, which triggers the behavior I just described and subsequently crashes with an error when a type check fails. However, once execution begins there's nothing stored on an object itself that identifies its original declared type. Everything in memory is either an atom, sequence, or integer by way of some internal bit-twiddling. The interpreter itself simply cannot know if you declared that 1 as an atom or an object or a map or whatever else. It's up to the UDT function to check the value of the object and return a pass/fail result.
Nested maps: When you create a map with new it just allocates a slot in Pseudo Memory (a.k.a. "eumem") which is just a way to create global "handles" for pass-by-reference. The map UDT just checks that the value is an atom, is a valid ID in eumem, and the does some internal bounds-checking. The nested_put routine is just a recursive call that "loops" through a sequence of keys, creating sub-maps as required. As long as the value stored in a key looks like a map ID, nested_put() assumes it is a map and uses that map for the next key in the sequence, even if the value is supposed to be just a number.
Saving maps: The save_map isn't ever concerned with nested maps. It just wants to write one-map-per-file, period. In fact, load_map very specifically resets the file position to zero each time it is called, so it's impossible to read more than one map from single file using that routine the way it is. It's probably best to think of these routines as a way to cache a map on disk, perhaps for storing a complex lookup table without having to regenerate it each time your application starts. If I was involved at the time, I think I would have argued against adding both nested maps and save/load since the two features are mutually exclusive.
So short answer to your question is: maps do not work that way. Sorry. But, if you're only looking to store and load a map-of-maps, then that is relatively straight-forward, and I made a demo for you: https://openeuphoria.org/pastey/357.wc
-Greg