This page is part of the web mail archives of SRFI 38 from before July 7th, 2015. The new archives for SRFI 38 contain all messages, not just those from before July 7th, 2015.
> Look at this, please, from the perspective of having a well-behaved > function that can write an external representation of data so that it > can be read back in recovering the same structure, and you will see > that it's a completely different issue from presenting the data in a > particular style, format, or radix. Such details are irrelevant here. This is not at all my perspective. I manipulate large cyclic data structures all the time (doubly-linked lists, trees with back-pointers, object system class descriptors, etc), my programs (sometimes!) have bugs and I want to dump these cyclic data-structures nicely so that I can figure out what the problem is. I do this all the time! It would be a shame if I could not combine the pretty-printing feature with the shared data printing feature. My point is that these features are not mutually exclusive, so the API should be designed to let the user pick the features needed. Moreover, if you are truly trying to design a procedure that will allow data to be read back and recover the same structure, then there are still plenty of on/off switches that you can give to the user (and that you eventually will have to as the needs of users evolve): - Should hidden fields of an object be written or not? This is useful for debugging but also for saving an object to a file and reading it back in later. - Should numbers that are eq? be marked as shared or not? For example in (123 . 123) both numbers are probably eq?, and perhaps also in (0.0 . 0.0). - Should the low-level code of procedures (bytecode, or whatever) be dumped? Same issue for continuations. - Should the object be written as text or in binary? After all if a human is not going to read the data using text is just wasteful. A binary representation, or even a special purpose textual representation would be more compact. So in the end the "write-showing-shared" procedure still needs parameters. We don't yet know how many we need (and probably never will as the need for new features never ceases to grow). This is why an API based on dynamically bound parameter objects is needed. Alternatively, explicit keyword parameters could also be used: (write obj port shared: #t pretty: #t) I have also found readtables to be a good way to package up the parameters that are used by "write" and "read". The readtable specifies the external representation and "write" and "read" use the readtable when generating the external representation or when parsing an object. With readtables you would have: (let ((rt (readtable-copy (current-readtable)))) (readtable-allow-sharing-set! rt #t) (readtable-pretty-print-set! rt #t) (parameterize ((current-readtable rt)) (write obj port))) or (let ((rt (readtable-copy (current-readtable)))) (readtable-allow-sharing-set! rt #t) (readtable-pretty-print-set! rt #t) (write obj port readtable: rt)) Marc