[Top][All Lists]

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

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

From: Davis Herring
Subject: Re: `read--expression' and `read-minibuffer'
Date: Wed, 7 Sep 2016 11:01:40 -0600
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.3.0

It affects completion, as has already been stated: given
(comment-c as 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.

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?

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

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

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. The only escape is the notion that the author used the function, despite a semantic mismatch, because there was no better choice available or because they didn't know about it. Either of those constitutes a bug -- the former of laziness, and the latter of ignorance.

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.

Rice's theorem, of course, denies most progress beyond that point: you can try to count arguments, for example, but as has been discussed recently that is fraught with peril in the case of advice-like function wrappers.

We nonetheless can offer a rigorous definition of a form such that all expressions which evaluate without error are forms, even though not all forms evaluate without error (and some of them have variable behavior).

And what makes you assume that it would if it could, that is,
that it even cares only about expressions that could be evaluated
without error?  Why not accept it for what it is - characterize
it by its actual behavior (which is to read any syntactically
valid sexp).

That's like characterizing Emacs as a compiler because someone chooses to write an object file in it with C-q. The tailoring of the tool, not the result of its use in any particular instance, defines its purpose.

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"!)

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. `universal-argument' "actually returns" the "exit function" created by `set-transient-map'. But it doesn't document that behavior, because we prefer the flexibility of changing it to the (marginal) utility to the caller of `universal-argument'. (For example, in Emacs 23 it returns t; should the current implementation contain a stray "t" to retain that behavior?)

So you say, with nothing but hand-waving to back it up.  That's
presumptuous about what a caller wants to get from the user and
what it wants to do with what it gets.

What I have offered to "back it up" appears minuscule only in comparison to the redundant text arguing about it (much of it snipped here).

`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)?

That's why we have the documented contract -- to let us know whether you were in error to rely on it for "off-label" uses, 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", 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".


This product is sold by volume, not by mass. If it appears too dense or too sparse, it is because mass-energy conversion has occurred during shipping.

reply via email to

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