[racket-dev] current-*-port

From: Eli Barzilay (eli at barzilay.org)
Date: Fri May 4 17:18:50 EDT 2012


Yesterday, Matthias Felleisen wrote:
> I don't think Eli is proposing an elimination of the old names but
> supplementing the code base with new ones.

Yes, I'm suggesting something along the lines of a simple addition to

  (provide (rename-out [current-output-port stdout] ...))

so they even keep the old printed names.

Yesterday, Ryan Culpepper wrote:
> FWIW, 'eprintf' has almost completely eliminated the need to ever
> type 'current-error-port' for me.

Yeah, I suggested adding it for the same reason.  (And because
practically any program that I wrote had a definition of it anyway.)
But it's still common enough to rewire ports, which makes the long
names still used pretty often.  A common example:

   (subprocess (current-output-port) (current-input-port) (current-error-port)

Yesterday, Neil Van Dyke wrote:
> I'm not sure how I feel about shortening these, but an additional
> consideration is that a naming convention for parameters (so far,
> prefixing with "current-") has been useful.  I think a naming
> convention can help remind people that this won't work with renaming
> alone:
> (fprintf stderr "Oops!")

Yes, I'm aware of that...  There are two ways that I can think of to
go around it:

1. Make the shorter names identifier macros that evaluate to the
   parameter value.  This requires some further hacking so that the
   parameter can be used when needed.  For example, add some syntactic
   form where the return-the-parameter-value behavior is suppressed.

2. Make the primitive layer for all functions that consume ports
   accept a parameter (or a thunk) that produces a port too, and apply
   it to get the value.  (The idea is that if the port-consuming
   primitives change like that, then any abstractions built on them
   inherit the same.)

The first is pretty bad IMO, since the names become more magical than
the usual identifier macros.  I view the second as a better approach,
and one that I wouldn't mind either -- but that's a much deeper
change.  (At least for anything type-like it will be a headache.)

Yesterday, David T. Pierson wrote:
> On Thu, May 03, 2012 at 03:48:17PM -0400, Eli Barzilay wrote:
> > IMO, anyone who is not coming from some kind of Scheme background
> > would view this as ridiculously long.  If they're renamed to the usual
> > names, things look much better:
> > 
> >   (parameterize ([stderr (stdout)])
> My first thought is that the names current-error-port and stderr
> suggest different concepts.
> stderr is the standard error stream corresponding to POSIX file
> descriptor 2.
> current-error-port is an abstraction mechanism that allows you to
> control where error messages are directed.
> If stderr were to be bound in #lang racket, based on the above I'd
> expect it to be bound to a port corresponding to the standard error
> stream, not bound to a parameter controlling which port error
> messages go to. [...]

It is doing just that -- it just happens that it's easy to redirect it
(already) so that error messages go to a different port.  It's pretty
the same terminology as used in shell scripts, where you can redirect
the IO of a single function call so FD number 2 is either the error
stream of the whole script, or whatever it was redirected to in this

[BTW, the analogy also holds wrt debugging code that makes heavy use of
such redirections -- if do this kind of debugging in a shell script
I'd use something like this to make the debugging show on the

  echo "blah" >> /dev/stderr

and I do the same in Racket:

  (with-output-to-file "/dev/stderr" #:exists 'append
    (λ () (printf "blah\n")))

I think that CL solves this nicely: in addition to the standard
input/output ports, you also have `*query-io*', `*debug-io*',
`*terminal-io*', and `*trace-output*'.]

> Also, I see that these names appear to already be available as
> proposed via the preprocessor/mzpp and preprocessor/mztext modules.

Heh, yes -- the author of that library happens to share many opinions
with me, so he defined and provided exactly the same shorthands:

  (define stdin  current-input-port)
  (define stdout current-output-port)
  (define stderr current-error-port)
  (define cd     current-directory)

(In case it's not clear, I wrote that code -- and I made these
shorthands exactly because such redirections are something that you'd
use extremely often with the kind of preprocessing that those
libraries do.)

          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                    http://barzilay.org/                   Maze is Life!

Posted on the dev mailing list.