[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: `read--expression' and `read-minibuffer'

From: Drew Adams
Subject: RE: `read--expression' and `read-minibuffer'
Date: Wed, 7 Sep 2016 14:01:03 -0700 (PDT)

> >> a _form_ (hopefully less ambiguous than "expression"),
> >
> > (No less ambiguous.)
> Why not?  It's defined in the Emacs Lisp Reference Manual, and it's
> not a generic term of art from parsing in a variety of contexts.

I already addressed that.  Again: In the Elisp manual, node
`Intro Eval', "form" is given as a synonym for "expression".
And both are mentioned as synonyms for both "S-expression" and
"sexp" (which the manual generally avoids using).

> > All of that has already been said, by each of us.  I said it at
> > the outset.  It's clear that the completion it provides is for
> > function names after `('.  No one disputes that.
> And thus a user who was expecting to enter the cons (comment-column .
> 40) would be surprised, would they not, when the completion chose
> something else?

Unless `comment-column' has also been given a function definition
in the user's session, completion of `comment-c' after `(' would
not provide `comment-column' as a candidate.  This has all been
said multiple times now.

But a user could type `(2 commment-c', `TAB' to complete to
`(2 comment-column', and then remove the 2.  For a long name that
is not memorized, such completion can help.

And for a variable or function name in the current buffer, `M-/'
and `C-M-/' provide completion anywhere, including just after `('.
Again, for a long name, such completion can help, regardless of
whether the sexp read is evaluable without error.

And using completion or not, a user can certainly enter
`(comment-column . 4)', and that dotted list is what is
returned by `read--expression'.

This has all been covered already in this thread.

Why do you reply to:

  It's clear that the completion it provides is for
  function names after `('.  No one disputes that.

by belaboring that point, as if you are divulging it?  TAB
completion of a name after `(' is function-name completion.
Yes, and so what?  `read--expression' is not _limited_ to
reading only function names after `('.

> Isn't that enough of a reason to acknowledge the function's
> predisposition towards reading forms, not general values?

Predisposition for completing a function name after `('.
It is not limited to reading list sexps that only have a
function-name car.

> > And what it reads and returns is not limited by the (handy,
> > for some expressions) completion it provides.
> No one is questioning its _capacity_ to accept other data
> from the user.

And no one is questioning that it provides function-name (only)
completion after `('.

> (But if capacity is all that matters, you might as well use a normal
> `read-from-minibuffer' and call `read' on the result yourself.)

That's the point of this thread.  No.  `read--expression' is
handier for many sexps, including some that are not lists with
function-name cars.

It's not black-&-white.  Each read function, according to what
it actually does, has its own advantages and use cases.

The point (#1) is that the useful uses of `read--expression' are
not limited to reading lists with function-name cars.  In some
contexts, completion of function and variable names can be useful
for reading other sexps.

And the point (#2) is that the usefulness of `read--expression'
is not limited to Emacs developers - it should not be considered

> > And even that completion says nothing about the intended use of
> > what is read, in particular about any intention to evaluate it.
> Nonsense -- that choice of completion mechanism, coupled with the choice
> of the caller to use a function that provides it, indicates plainly that
> the code's author meant for a form to be entered.

It's not about the author of `read--expression'.  It's about its
users and their intentions.  Why particular code reads a sexp -
any sexp, is up to it.  You cannot assume that it will then be
evaluated by that code.  And that stands for any read function,
including `read--expression'.

> >> They have a structure that could possibly evaluate without error?
> >
> > Is that really how you want to define "expression"?  So `(/ 3 0)'
> > is not an expression, _because_ it raises an arithmetic error?
> > Or do you want to backtrack a bit, and settle on just syntax
> > errors?  Or on some other kind of error?  See my previous message
> > about this.
> No backtracking: I already said "could possibly evaluate".  No
> dotted list (e.g., (/ 3 . 0)) can ever evaluate.
> You can also determine that the list (3 0 /) will not evaluate
> successfully without any semantic understanding, because 3 is
> not a function.  Somewhat less reliably, we
> can determine that the list (comment-column 40) will fail under
> evaluation because `comment-column' is void as a function.

But none of that is what `read--expression' does.  It happily reads
(/ 3 . 0), (3 0 /), (comment-column 40), and (comment-column . 40).

What it does not accept (it raises an error) is a syntax error,
i.e., a Lisp _read_ error, such as an isolated `.' or `,'.

What it does is read and return a Lisp sexp, and not only one
that `eval' can handle without error.

And what if your code even _does_ intend to evaluate a sexp read,
but only after its symbol car gets defined?  Will your "improved"
`read--expression' be right in not accepting (foo 42) because, at
the moment of reading, `foo' is not yet defined?  So much for its
guessing intention of evaluation.

> > And note that the doc of `read' too talks about reading a "Lisp
> > expression".  It does not exclude `((a . b) (c . d))' or any
> > other syntactically valid sexp from the class of "expressions".
> In that context, "expression" is set against "object" and plainly refers
> to the textual representation.  (This is why I switched to the word
> "form"!)

(Again ((elisp) `Intro Eval'), for Emacs, "form"="expression".)

And yes, of course it is setting "expression" against "object".
That's what a Lisp read function does, and `read--expression' is
no exception.

In the language of Common Lisp (CLTL2, 22.1.1), the Lisp reader

   "accept[s] characters, interpret[s] them as the printed
    representation of a Lisp object, and construct[s] and
    return[s] such an object."

> > A better interpretation is based on what the function actually
> > does, I think: what it reads without error and what it returns.
> "Actually does" is a poor choice.

Info that helps the user about what `read--expression' does:

. It reads a Lisp sexp from the minibuffer.
. For symbol names, it provides completion using `TAB'.
. For a symbol name after `(', only function names are completed
  using `TAB'.  (Function in the wide sense: macro, special-form,
. For a symbol name anywhere else, function and variable names
  are completed using `TAB'.

(And `M-/' and `C-M-/' complete to names from the current buffer.)

> > `read-expression' is handy for reading lots of sexps that do not
> > fit your characterization of intent - simply because that's what
> > it actually does: reads and returns a sexp.
> So you find the (undefined) behavior of its current implementation
> useful.  
> What if you start relying on it and then someone else changes
> it to do the sanity checks I discuss above (because, say, they want to
> get better error messages than the evaluator gives, or they want to stop
> the user from exiting the minibuffer with invalid input)?

We'll cross that bridge when we come to it.  For now, the only
request has been to remove the extra hyphen and not consider it
"internal", please.

> That's why we have the documented contract

Sorry, I must have missed that "documented contract".
Where is it? What does `C-h f read--expression' tell you?
"Not documented."

You said that the behavior is undefined.  So I say look at what it does.

> -- to let us know whether you were in error to rely on it for
> "off-label" uses, 

Sorry, where's the label?  ("Not documented.")

> or whether the implementer was in error to alter it.  We may choose
> that contract at our whim -- and at our peril.  There's no reason to
> suppose that the answer is "whatever it currently implements, exactly",

What reason is there to suppose that the nonexistent contract
would say, if it existed, that the answer is "whatever Davis says"?

> and less than no reason to choose "help the user type a form,
> but do not check its validity in any way in case the caller is
> expecting something else".

In the absence of any "documented contract", we can go by what
the function does.  Or we can go by what you happen to think
the function really wants to do but does not do.

So far, I'm content with what `read--expression' does and does
not do.  But it should be considered just as useful for an
ordinary Emacs user-programmer as it is for Emacs developers:
not "internal".

reply via email to

[Prev in Thread] Current Thread [Next in Thread]