Multiple items and keywords in display/print/write
For debugging, I use a lot of times
(displayln (list "Result=" x y z))
It would be nice to be able to write
(displayln "Result=" x y z)
So my proposal is that to change the signature of display/print/write to something like
(define (display #:port [port (current-output-port)]
#:separator [separator " "]
#:newline [newline #f]
. items)
...)
Python also has a #:flush keyword (or their equivalent version) and uses #:file instead of #:port, but I think #:port or #:output-port makes more sense. The real version is
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
More questions:
Is it better to use #:newline (boolean) or #:end (string/bytes) or #:end (any)?
Add #:start (string/bytes//any)?
Add #:before-last like string-join?
Collapse display and displayln in a single function?
Would an approach like printf that's based on format strings work instead?
(printf "Result= ~v, ~v, ~v\n" x y z)
It is totally possible but with printf I have to count the number of arguments and modify the format string each time I add or remove or #;comment a variable. It uses almost the double of characters.
More questions:
.
Unify e/f/printf with print?
Python has:
-
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False) -
reprfor converting an object to a string that (hopefully) can be parsed back. E.g.,repr("abc")=="'abc'" - String interpolation via
.formatstring method. In recent Python,f"..."literal string subsumes the method. E.g.,world = 1.2345 f"hello {world:10.3f}" #=> 'hello 1.234' - Deprecated printf-like string interpolation via
%operator.
Racket has:
-
print,write,display, andlnvariants, where the second optional argument is for specifying the port. It accepts exactly one argument. -
printf,fprintf,format -
~a,~v,~s - @-expression
My personal opinion is that printing in Python is far more friendly than in Racket.
-
write,print, anddisplayare similar but subtly different. It is not friendly to beginners who are overwhelmed by all these functions. They just want to show something on screen!- Object printing requires you to implement at least two methods (and at most three). For people who just want to display an object on screen, this is really inconvenient.
- I believe that most regular programmers would use
displaymore thanwrite(or evenprint).writeonly makes sense when you want toreada datum back, but I don't think most programmers will do that. - What if we remove
(write x), and replace all uses with(display (repr x))whererepr=~s. Does this reduce the complexity?
-
The inability to accept multiple arguments for
print-like function is probably to maintain backward-compat to Scheme. Being able to print several objects in one invocation is obviously better, especially for debugging purpose, and it should be easy to implement this by moving the port argument to keyword argument. -
I wish for
f"..."-equivalent construct in Racket. Currently, this could be approximated by(let ([world 1.2345]) @~a{hello @(~r world #:precision 3)})(see https://www.greghendershott.com/2015/08/at-expressions.html), but we need to full @-expression for it to work. Also, it seems verbose somewhat...- I really dislike
printf. I need to go back and forth between the format string and argument list. I think Python made the right call to switch to the newer string format.
- I really dislike
-
I think we should have both
printandprintln. In some Python projects I sawend=''all over the file. That seems not ideal.
I have some concern re: keyword argument. The port seems to be suitable for keyword argument because if users want to call print only a few times, then it's OK to write (print ... #:port ...). If they want to call it a lot, they'd better switch to (with-output-to-port ... (print ...) ...), so that's OK as well. But stuff like #:precision in ~r somehow gives me a different feeling.... So when is keyword argument acceptable, and when is it not?