Subject: RE: bug#32064: 26; doc string of `eval-last-sexp'

From: Drew Adams <[email-masked]>
Date: Fri, 6 Jul 2018 10:55:19 -0700 (PDT)

> >> I agree.  I think the solution is to simplify the interface somewhat.
> >
> > These additional features weer added just recently, so I see no reason
> > why we should remove them now.  Certainly not because the doc string
> > needs to be fixed.
> 
> >> As it stands, we're trying to cram a lot of functionality into the
> >> prefix argument, and the encoding is too difficult to remember (both
> >> in terms of implementing & documenting, as well as for using).
> >
> > I had no difficulty bringing the doc string in line with the
> > implementation, please take a look.
> 
> Thanks, I think that fixes all the typos and mistaken descriptions.  I
> am still of the opinion that the prefix args apart from C-u are too
> complicated to be of much use.  But we can wait a bit longer and maybe
> the next formatting feature will be the straw that breaks the proverbial
> camel's back.

Thanks for the doc string corrections.

I agree with Noam that the behavior is not great.  It's not
very user-friendly or very useful.  It should be rethought,
even at the cost of backward incompatibility.  Perhaps a
new, replacement command should be added and given the
key binding, keeping the old command available for whoever
wants to restore its binding.

I started to write a mail to emacs-devel about this
yesterday, but I dropped it, at least for now.

FWIW, I think it would be good if the various Lisp
evaluation commands acted more or less similarly - e.g.,
wrt a prefix arg.  There are several, including:

`eval-last-sexp', `eval-print-last-sexp',
`pp-eval-last-sexp', `eval-expression',
`pp-eval-expression', `eval-region',
`eval-defun', `eval-buffer', and
`lisp-eval-defun'

Something I've been thinking about is the need I have
to evaluate Lisp code with `lexical-binding' optionally
non-nil.

I know that the expectation of some (maybe all) is that
Emacs will eventually make non-nil the default value of
`lexical-binding', or even remove the variable altogether
and make binding lexical by default (the same effect as
having the variable default to non-nil everywhere, but
with no ability to change the behavior to what nil gives).

FWIW, I have no problem with that, as long as dynamic
binding is still available - exactly the situation of
Common Lisp, and _not_ the situation of Scheme.

Still, it is now, and it can remain in the future, useful
to be able to grab a bit of code from anywhere and
evaluate it optionally with `lexical-binding' in effect.

I sometimes copy Lisp code from files I'm working on to
another Lisp buffer, to modify and experiment with.  The
buffer I copy it to might serve for code that comes from
buffers with nil and non-nil `lexical-binding'.

And it might not be a file buffer, or I might not have
bothered to add a local-variable declaration for it.
E.g. `C-x 4 f foo.el', for a non-existent file `foo.el',
does not default to non-nil `lexical-binding' (yes, I
could make it do that).

When I want to evaluate bits of code in such a test
buffer, it won't do to just use `eval-region' or
`eval-expression' or `eval-last-sexp'.  Depending on
whether the code to be eval'd _depends on_ lexical
binding, I need to first set `lexical-binding' as
needed, perhaps temporarily, for the whole buffer.

I'd prefer to have the evaluation commands take care
of this.  I can of course define separate commands for
lexical binding, like so:

(defun eval-region-lexical (start end &optional printflag
                            read-function)
  "..."
  (interactive "r")
  (let ((lexical-binding  t))
    (eval-region start end printflag read-function)))

But it would be handy if the regular commands would let
me provide a prefix arg to get that behavior.  E.g.:

(defun eval-region (start end &optional printflag
                    read-function lexicalp)
  "..."
  (interactive "r\ni\ni\nP")
  (let ((lexical-binding  (if lexicalp t lexical-binding)))
    (eval-region start end printflag read-function)))

That would work for `eval-region', because it currently
defines no prefix-arg behavior.

But for the other eval commands things are less simple.
They already use prefix args to the max (too much).  Like
Noam, I'd argue that the prefix arg behavior for some of
them is far too complex, if not tricky.  The resulting doc
is consequently pretty much a mess.

Can we come up with something better?  Maybe there needs
to be more than one command for some of these things that
are currently combined via prefix args (again, something
that Noam too suggested)?  Or maybe some better
combinations can be found?

You'll note that I included the `pp-eval-*' commands in
the list above.  I bind (a variant of) `pp-eval-expression'
to `M-:', for instance.  I'd like `pp-eval-*' commands to
also share in a reflection about better and more consistent
prefix-arg behavior.

---

FWIW, my variant of `pp-eval-expression' does the following.
I mention it for the info about prefix-arg behavior.  IOW,
I realize that different eval commands can have different
uses for a prefix arg.  Still, some more consistency, and
less complexity, than now would help.

- Read with completion, using `pp-read-expression-map',
  which is like `read-expression-map' but with some
  Emacs-Lisp key bindings.

- Respect option `eval-expression-debug-on-error'.

- With no prefix arg, respect option `pp-max-tooltip-size'.
  If a tooltip is not used then if the value fits on one
  line (frame width) show it in the echo area.  Otherwise,
  show it in buffer *Pp Eval Output*'.

- With a zero prefix arg, swap the use of a tooltip
  according to `pp-max-tooltip-size': if that option is
  `nil' then use a tooltip; if non-`nil' then do not use
  a tooltip.

- With non-zero prefix arg, insert the value into the
  current buffer at point. With a negative prefix arg, if
  the value is a string then insert it without enclosing
  double-quotes (").