Home   Archive   Permalink



Formatted memory dump

No question here, just a comment. I just ran across this concept by accident so I thought I would mention it. Probably everyone knows this but me. It solves, at least partially, something I always though one ought to be able to do in REBOL, which is make a "memory dump" that could be invoked on some error to show what is in the program at the time of the error, as a debugging aid.    
    
From the documentation of the "in" function I see that if you have an object, the "first" function returns all the words in it, and the "next" function applied to that list of words skips over the first word which is some sort of system-generated word called "self." What is left is the words in the object. In other words, it is possible to write code to obtain all the words in an object without having to hard-code those words in some sort of list.    
    
What that means is that if you structure your code so that everything is in objects, then each object could have a short little "dump" function to print its own contents in a formatted manner, either to the console or to a file. A dump would be for one object only, but that could actually be good, and it would not take a lot of lines of code to invoke the dump functions for every object in a multi-object program.    
    
I haven't worked out the details about how far one could push this to make a formatted memory dump of everything in a large program (layouts, local function variables), but just this small capability for plain words in single objects could be handy. Following is a test script that shows it.
    
R E B O L [
     Title: "Dump test"
]
    
TESTOBJ: make object! [
     NAME: ""
     ADDRESS: ""
     CITY: ""
     STATE: ""
     ZIP: ""
     DUMP: does [
         WORDLIST: sort next first TESTOBJ
         foreach WORD WORDLIST [
             print [in TESTOBJ WORD ":" get in TESTOBJ WORD]
         ]
     ]
]
    
TESTOBJ/NAME: "STEVEN"
TESTOBJ/ADDRESS: "1800 W OLD SHAKOPEE RD"
TESTOBJ/CITY: "BLOOMINGTON"
TESTOBJ/STATE: "MN"
TESTOBJ/ZIP: "55419"
    
TESTOBJ/DUMP
    
halt

posted by:   Steven White       1-Apr-2014/16:27:45-7:00



If you want to inspect the object itself without relying on the TESTOBJ word, meaning the object could have any name, use SELF in the DUMP function:
    
    DUMP: does [
         WORDLIST: sort next first SELF
         foreach WORD WORDLIST [
             print [in SELF WORD ":" get in SELF WORD]
         ]
    ]
    
My optimizations, as an exercise:
    
    dump: does [
     foreach word sort words-of self [
         print [word ":" get in self word]
     ]
    ]
    
Explanations:
    
- WORDS-OF is the now formal style of using FIRST, as FIRST may not work in future versions of REBOL. Also NEXT is not needed with WORDS-OF.
- WORDLIST is not necessary and was leaking out of the function, because DOES was used. To prevent it from leaking, use HAS [WORDLIST].
- using IN TESTOBJ WORD is not really necessary, as your NEXT FIRST already makes a complete list of words. IN is better suited for checking whether the object contains the word.
    
On a less related and a bit deeper note: When making objects, it's a good idea to pay attention to when you need to have functions inside them. A DUMP function is quite generic, and so carrying that around inside an object can be a little heavy on the memory usage, particularly if you have thousands of copies of the same object in your program.
    
We can test this, by making a copy of the object in the most typical way:
    
    testobj2: make testobj []
    
    >> same? get in testobj 'dump get in testobj2 'dump
    == false
    
SAME? tests if two values are really the same item in memory. In this case, they are two separate items.
    
Which means there is now a copy of the function in the new object. Now imagine thousands of copies of the same function...
    
This is why I try make functions that act on objects instead of trying to make objects "smart", of course depending on the context, so it would be:
    
    dump test-obj
    
And it would look like this:
    
    dump: func [obj] [
     foreach word sort words-of obj [
         print [word ":" get in obj word]
     ]
    ]
    
Finally, try this built-in function:
    
    print dump-obj TESTOBJ
    
or simply:
    
    ? TESTOBJ
    
They do not sort, however.

posted by:   Henrik       2-Apr-2014/6:02:42-7:00



Well thank you, this is a memorable day, for two reasons. Reason number one is that once again I see that there is stuff in REBOL that I didn't even imagine existed (although I guess I did wonder briefly what that "self" word might be used for). But reason number two is, I read your explanation and actually understood it. Not that you don't explain well, but that REBOL is becoming less obscure, to the point where things like this start to make sense.

posted by:   Steven White       2-Apr-2014/9:31:10-7:00