(Previous discussion continued)
|
||
Re: new function or modify read Marc Feeley (18 Dec 2002 15:47 UTC)
|
Re: new function or modify read Marc Feeley 18 Dec 2002 15:47 UTC
> > - 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. > > This is immaterial since "hidden fields" are a completely undefined The list of on/off switches I mentioned in my message was just an example to show that many variations exist. I was not suggesting that you add them to the SRFI, in fact for most of the switches it is clearly premature to finalize a design. My point is that there are many variations to "writing data so that it can be read back". The fact that many of them are implementation dependent is not important. It just means that individual implementors will be faced with the problem of expressing these variations. Because there are so many variations (at least at some point in the future) and they are not mutually exclusive, the variations should not be expressed through the name of the procedure. Parameters should be used. Your choices are: 1) positional parameters 2) keyword parameters 3) dynamically scoped parameter objects I have expressed my preference between these three. But this preference is a detail. The important thing is to have a parameterized procedure. Let me move on to a second topic. Orthogonal to the particular parameter passing being used is the issue of whether the options should be packaged or not into one structure. This can be a procedure, as you suggested, or as a data structure, that is the "readtable" that I suggested. Now don't be fooled by the name "readtable" which was chosen for historical reasons (and because it is a short name). It is really a data structure that specifies the external representation of data. This information is both useful for "write" and for "read". In fact, to guarantee that "read" is able to read data that has been written with "write", the same readtable must be supplied to "read" and "write". For example, here is some of the information that can be found in a Gambit-C readtable: - Whether sharing is allowed (i.e. the notation #0#, #0=...). - The maximum depth and length that should be written. - Whether case should be preserved in symbols, character names, etc. The choices are: yes, no and map to lowercase, no and map to uppercase. - Whether keywords are allowed. The choices are: no, yes and ":" is at end, yes and ":" is at start. - Whether control characters in strings should be escaped. - The set of characters that can be escaped in a string (i.e. \n, \\, etc). - The set of characters that are named (i.e. #\space, #\newline, etc). - The set of special #! objects (i.e. #!eof, #!void, etc). - Whether evaluation is allowed (i.e. the notation #.<expression>). - The formatting rules for pretty-printing. Once again this is just an example. I'm not suggesting that you handle all of these. You could limit yourself to the first one and leave the "readtable" type open for extensions. Readtables and dynamically scoped parameter objects can be combined in an interesting way. Imagine that to each port is attached a parameter object that corresponds to the readtable that is used for calls to "read" and "write" on that port. When a port is created some sort of "standard" readtable is used (which makes "write" and "read" behave as specified in R5RS). Suppose that (port-readtable-parameter port) returns the parameter object that is attached to the port and that (readtable-shared-set readtable flag) returns a copy of the readtable where the "shared" option is set to flag (it does *not* mutate the readtable passed as an argument). This gives a very flexible API: - You can "write" in a standard way: (write X port) - You can setup a port so that all output is in a particular style: (let ((port (open-output-port "foo"))) (let ((rt-param (port-readtable-parameter port))) (rt-param (readtable-shared-set (rt-param) #t))) (write X port) ; uses the sharing notation (write Y port) ; uses the sharing notation ) - You can temporarily do output in a particular style, on a specific port: (let ((port (open-output-port "foo"))) (let ((rt-param (port-readtable-parameter port))) (parameterize ((rt-param (readtable-shared-set (rt-param) #t))) (write X port))) ; uses the sharing notation (write Y port) ; uses the standard notation ) - You can have different threads doing output in their own particular style (this could be useful if you have a REPL thread and a "main program" thread and you want output from the REPL to be in a particular style): (let ((port (open-output-port "foo"))) (thread-start! (make-thread (lambda () (let ((rt-param (port-readtable-parameter port))) (parameterize ((rt-param (readtable-shared-set (rt-param) #t))) ...body of the child thread...))))) ; uses the sharing notation ... ; the parent thread uses the standard notation ) Again I'm not suggesting you go this far. The main point of my message(s) is to make your procedure parameterizable so that such extensions are possible (to be defined in other SRFIs). Marc