2015/08/07
Write control variables
Oh well. More than a year since the last entry. So many things has loaded into HEAD and I have to wrap it up as 0.9.5. Some small issues to address, though.
As a part of improving REPL experience, I implemented CL-like
write control variables. Those like *print-length*
. In
Gauche it looks like a parameter.
gosh> (parameterize ((print-length 5)) (write (iota 10))) (0 1 2 3 4 ...)#<undef>
I wanted them every time I accidentally evaluated huge data structure on REPL and just waited Emacs to finish showing it until the end (Ctrl-C can stop Gauche printing it, but it's mostly Emacs that's taking time to fill the buffer, especially when font-lock mode is on.)
By the way, print-base
comes handy as desktop calculator
for base conversion:
gosh> (print-base 16) a gosh> (print-radix #t) #f gosh> 4758375874 #x11b9f0dc2
Now I've implemented four of various CL's printer control variables, and sit back and am thinking. Are they really useful as they seem to be?
The global nature of those controls is the problem. I'd like to
limit print-length
on REPL output to avoid excessive output.
But doing so globally affects every operation, such as
serialization to file or network connection, which is almost certainly
undesirable. I can create a custom printer for REPL that changes
the controls only when it prints the result, but then I need
another set of API to set those values REPL would use.
Worse, now every routine that writes out values expecting it to
be read back must be wrapped with parameterize
to ensure
those control variables are in the default value, otherwise it
can be broken accidentally when called with print-level
set to 5.
The more I think, the more dubious I became about the CL's choice of making them dynamic variables.
Another idea I had before is to have a "context" object that packages
those controls, and you can set it to a parameter, instead of
parameterizing individual controls (the name ScmWriteContext in the
source was somewhat intended for that, but ended up for different
purpose.) With that, the REPL can have just one
repl-default-context
and use that for just printing.
Recently I got yet another idea; let a port have those controls. We already have port-attributes to associate key-value pairs to ports. For serialization you'll usually create a fresh ports so the chance of inadvertent interference is very low. For REPL output, we can create a wrapper port connected to stdout so that it can have separate attributes, and use it for printing the results.
Some more pondering.
Post a comment