Hi, my name is Eduardo Ochs,
and this is my video for the EmacsConf 2025.
Its title is Some Problems of Modernizing Emacs,
and that is the same title as a video
that I tried to record in March.
But my video from March had a good "beginning" and a bad "rest",
and I thought, I can't release that because the rest is very bad.
I need to replace... to re-record the last part of the video.
But I never did that.
So this video is going to be the first 12 minutes
of that other video, with another ending.
And in this other ending, I'm going to show some things
that are very easy to test. And, if people are interested,
then the rest of the old video will make more sense.
Anyway, let me start.
Hi! My name is Eduardo Ochs. I'm the
author of an Emacs package called eev and
the title of this video is
"Some problems of modernizing Emacs".
Here is a summary of the main themes
of this video. I'm going to talk mainly
about these four things here. The first
one is that Emacs has changed a lot in its
recent versions, and now it has lots of
types... so if we want to look under the
hood and to understand what Emacs
really does we are going to stumble on
lots of types... and the
current tree of classes and types
looks like this... that is,
is quite big.
The second theme is that people used
to say things like "Anyone can learn Lisp
in one day"... I'm going to explain
this quote, and I'm also going to show
that now this is gone... anyway. This is a
very short summary... details soon.
I will also show how to display
better "inner views" of Emacs objects...
I'm going to Define what is an inner view,
of course.
The main trick is that we are going
to use one of the ways of displaying
internal objects, that is the `cl-print'
family of functions, for example,
`cl-prin1-to-string', and here are some
examples of the kind of output that we
are going to see...
for example, if we run these two lines
here the first line defines a function `foo'
and the second line sets `o' to the
internal view of the definition of `foo'.
In older Emacses `o' would be just a
list that looks... that would look very
similar to this line here... but in newer
Emacses the result of this - I mean, the
the contents of `o' is this thing here,
that looks quite different
from this definition.
So, in older Emacses
the contents of the
function cell of `o'...
sorry, of the function cell of `foo',
would be an "old-style lambda",
that would be just a list like this...
and in newer Emacses uh the contents of O would
be a "vector-like lambda"... look for the
square brackets here - this is a
vector, but it is preceded by a hash sign.
So this is what we call
a "vector-like lambda",
and vector-like lambas do not
have a canonical printed representation -
they have at least two semicanonical
printed representations...
The first semicanonical
printed representation is this one, that is
generated by a family of functions with
names like `prin1'...
and the second semicanonical printed
representation is like this -
it looks like a list...
it looks somewhat like this definition
of `foo' here, but it has this
`:dynbind' symbol here...
and it turns out that when we use
the `cl-print' family of functions we can
reconfigure how things are printed...
and I'm going to show several interesting
ways of reconfiguring how lambdas are printed,
and one of the ways is going to
be like this.
We can also use the `cl-print'
functions with my indentation tricks to
to display how types, or classes, are
viewed internally by Emacs, and this is a
big example...
This is what Emacs considers as being
the definition of the type
`cl-structure-class',
class and it is this big thing here.
I edited it very lightly...
I just uh deleted some line breaks here.
And another thing that I want to to
explain is that Emacs
has some help functions that
I have never liked...
for most people they are good enough,
but for me they aren't... they...
uh, well - I'm going to say
more about this later...
and, for example,
if we want a description of what is
this type here, that we just saw in
its internal view here...
we can run either `describe-type'
or my variant of `describe-type',
and we get a help buffer
that looks like this, in which
these blue things that are underlined
are "buttons", in the classical sense...
you can click on these buttons, or type
RET on these buttons, and you will be
taken to another help page, that is
generated dynamically...
and you can navigate back and forth...
and well, whatever...
and I'm going to explain my
problems with these kinds of help buffers
and what I'm trying to do to
overcome these problems...
One of my slogans in this video
is going to be this one:
"Anyone can learn Lisp in one day".
this is a part of a bigger quote
that I took from a keynote presentation
by Abelson and Sussman, who
are two dinosaurs of Computer Science...
Here is the full quote:
"Anyone can learn Lisp in one day -
except that if they already know Fortran
then it would take three days."
This is a frame of the video...
By the way I am going to to add
this... "and if the person is starting
with Doom Emacs then it would take 5 years."
why? I'm going to explain why.
This is how Emacs used to be.
If we execute these two expressions here
the first one... sorry, each symbol can
have two "values",
one is its "value as a variable"
and another one is its "value as a function"...
and if we run this we store 42
in the "value cell" of the symbol `foo', and
if we run this defun here it stores a
certain anonymous function in the
"function cell" of the symbol `foo'...
and in Emacs, until some time ago
if we did that and and if we ran
this expression here the result
would be 42,
because of this line here, and if we
ran this line here the result would be
the anonymous function corresponding to
this defun here...
but now this has changed...
the result of this thing here is this
vector-like lambda here - but that doesn't
matter much now...
So, until some time ago
if we did that and if we ran
this expression here, (foo foo)...
Emacs would do this: it would
replace the first `foo' by this
anonymous function here, it would replace
the second `foo' by the value of `foo' as a
variable, that is 42,
and it would evaluate this, and the
result would be 420.
So, again, we used to have this slogan
here, "anyone can learn Lisp in one day"...
but now this is gone.
Let me show... let me talk
a bit more about why...
the title of this slide is
"Lambdas for beginners broken"...
if we run this, as I've shown
in the previous slide...
in the old style, in old Emacses,
the result of (symbol-function 'foo)
would be this anonymous function here...
and now we get this strange thing here.
So, this is an "old-style lambda",
this is a "vector-like lambda",
and until the middle of 2024
beginners could learn a lot of Lisp
by thinking only in terms of
objects like these...
this is a function and this
is an anonymous function, and
they would learn how to draw cons cell
diagrams like this thing here and this
thing here...
they would think on lists as
being these trees here, and they
would be able to understand a lot of
Lisp just by thinking in these terms...
and then vector-like lambdas started
to appear in many places... and if we use
"vector-like lambdas" in a wide sense,
to mean all the new objects,
these new objects, that are
difficult to visualize... they also started
to appear in many places.
This is a continuation of the
previous slide - this part here is a copy
of things that were in the previous slide...
before 2024 beginners could
open black boxes like this...
they could try to see what was in the
function cell of the symbol `foo'...
and they would see something elegant and
mind-blowing... and they would start to love
Lisp immediately.
Now what they get - what they see -
is a tiny part of a very complex structure
that is very powerful but that is
very difficult to understand...
and now our beginners are overwhelmed
instead of mind-blown.
Note that I said "black box" here.
Let me explain the term.
We can open what's inside of `foo'...
we can open `foo' to see the contents of
the symbol `foo', and we can try to see
what's in the function cell of the
symbol `foo'...
so we can open the box, but what we get
is something very difficult to understand,
and so I'm going to say that
when this happens that box is black.
It is not totally black - we can open open it -
but we don't understand what is going on there,
so we declare that that is black.
And... when these things started to happen
_I_ was overwhelmed -
and in this video I'm going to pretend
that I was not the only person
that was overwhelmed
by these new structures
that are not so elegant
as the ones that we had before.
Anyway...
Anyway... In the beginning of the video,
I said that I was going to replace
the second part of my video from March
by something that was very easy to test.
So this is a quick demo for the _very_ impatient.
I'm recording this in December for the EmacsConf 2025.
This is the demo that I'm going to present.
The idea is that people can run the demo a first time
just to check that everything works
and to have a notion of how things look like,
and then, in a second moment,
they can rerun the demo more slowly
to understand what each step does.
So... we are in a file called "00-try-this"...
and the idea is that we can execute most of this file
just by typing `f8's in the right places.
Remember that when we type `f8'
on a line that starts with two red stars,
eev treats that line as a comment.
So... I'm going to start here...
Note that it says in the bottom
of the screen that this is a comment.
We are going to run this to download some files...
Now the files are there...
This `find-2a' here shows a certain file
at the window at the right,
but we don't need to pay attention to that.
And this thing `load's that file.
So... when we load that file,
it defines some functions here
that are going to be used
by the rest of the examples.
Now we can run this thing here...
note that we just defined some functions
and then we ran these functions here...
`find-eoutput-2a'...
and they show some things in the window at the right.
These things are boring.
When we run `adt-insert' with argument 42,
it just shows a 42, in this way...
The other ones show other numbers... and so on.
And... what happens when we modify
this function here, `adt-2',
by adding and removing advices to it?
The idea is that people can run
this thing here several times,
watching the window at the right,
because the results are going to be shown there.
So, in the first moment, when we run...
no, no, sorry, sorry, let me run it again.
In the first moment when we run `adt-2'
it just shows a 2, and then we modify it in a certain way,
and we run it again,
and now before showing the 2 it shows a 1,
mysteriously,
and then we add something to be run after the 2,
And we run it again,
and now `adt-2' shows these three things.
And then we remove the advices,
we remove these other things,
and when we run ADT2 again,
it shows only `;; --> 2'.
It's impossible to understand that in the first time,
so we can run that several times...
to see how things work.
And now we want to understand
what changes in the function `adt-2'...
how it is modified internally.
I'm calling that the internal view of the function,
and we are going to compare
several internal views of the function `adt-2'.
I'm going to reset the function `adt-2'
by removing the advices
and placing the advices on it again...
and if we just pretty-print this function here,
the symbol...
the value of this symbol here as a function,
it is something very ugly.
But if we print it in another way, with `cl-prin1',
then we get something that is much nicer...
but that is not indented.
And if we use this thing here,
`cl-prin2' instead of `cl-prin1',
it becomes indented.
So let's try it again.
Here is the current view of what is `adt-2'.
So, the original `adt-insert' is here...
and here are some modifications
that were added by the advices.
And we can run these things many times
to understand what each step does.
But my suggestion is: in the first time
just run everything very quickly...
and then you run it again,
paying attention to the parts
that look more interesting.
Now, I'm going to...
Remember that here
I printed the contents of `adt-2'
in several different ways,
and now I'm going to show how we can
do the same idea
of printing something in different ways
for lambdas...
that is something that I explained
in the first part of the video.
In this part of the demo
we define a function `foo'...
this `setq' here defines `o' as the
contents of the function cell of `foo'...
And now we are going to print
that `o' in several different ways.
The default way is this one, it's very ugly,
but we can redefine how these things are printed
by just running these lines...
and if we pay attention at what's happening
at the window at the right,
we can see that we have several different
printed representations for the same thing...
and then at the last step,
we reset the printer to the default representation.
And the details are here.
If we run these lines here,
they show the definitions at the window at the right.
And this... now comes the difficult part,
in which we have to do something
besides just running things with F8.
We need a help buffer with buttons...
buttons in the traditional sense,
and we need to choose a certain button there,
or any button there,
and run `M-x ee-set-button' on that button.
So, let me define a `struct' here,
and this is the...
some help on what is that structure.
I'm going to choose this button here
and I'm going to type `M-x ee-set-button'.
The message is a bit obscure.
And now we have something that displays
a lot of information about that button...
And we can also run that with just `F8's.
By the way, if we want to understand
the code that's behind these things,
we can run this sexp here.
It is going to show the code here at the right.
But anyway, these first lines here...
they display the output in the echo area...
Let's try...
And each one of them extracts a different part
of the information on that button.
And these other lines here create a three-window setting
in which the help buffer is shown here,
and the result of some other thing
is shown in the third window. Let's try...
So now that we have... well...
I said that we needed to choose a certain button
and run `M-x ee-set-button' there.
We have done that...
so now this variable `ee-button'
contains information about the button...
And now we can run this part here
as many times as we want to...
try to understand what are the values of these things here...
and how some things start with a value that is very complex
and very difficult to understand,
and then we extract the more interesting parts.
And the details, as I said, are here.
That was the end of the demo, and my question is,
what was your reaction to that?
If your reaction was more like "wow" than like "blergh"
then you might like the last part of the video that I recorded in March,
that was very technical...
When I recorded it, I thought, oh my god, this video is very bad...
only the hardcore eev users are going to like that,
and there are less than five hardcore eev users in the world...
But anyway, if you saw that introduction
and you think that these things are interesting,
you can execute any one of these S-expressions here
and take a look at the final part of that video
that describes how I wrote some functions
for exploring buttons.
If you execute this sexp here,
it plays a part of the video starting from that position.
If you execute this one, you go to the subtitles in HTML...
and if you run this one, you go
to the subtitles in another format. And... that's it!
No, no, sorry, I said "that's it",
but I forgot a very important part...
I had prepared this slide here
to explain some design decisions behind eev
and why there are so few users of eev...
and let me do that.
The thing is that my working memory is very small,
and I need examples that are easy to visualize...
ideally, examples that are easy to run
and that I can compare the outputs
of different ways of running them.
For me, understanding specifications
in an API is not enough...
examples work much better for me.
Also, I make lots of mistakes when I type...
so I need ways to run my executable notes
by just typing `f8' and `M-e'...
and... most people in the #emacs channel
and in other places recommend executing sexps
by typing `M-:', like this...
But I hate that...
I think that `M-:' and IELM are
for people who type well, so not me...
And also, 99% of what I do is scratch code.
Very few things that I do go
into "production" - between quotes.
So most of my tests are not automated tests.
They are just things that I run with F8,
and they don't include the expected result.
Many people feel that this is very, very, very wrong.
Tests MUST MEAN automated tests.
Also, and this is very frustrating,
eev has lots of "non-users",
I mean, people who have tried to use it,
but they said that they couldn't figure out how to use it.
They couldn't understand
what would be the workflows for eev.
And that's the same that happens with me
with code blocks in Org...
I'm still at the point in which code blocks in Org just feel wrong.
I still don't understand how to organize my workflows around code blocks.
I said that eev has very few users,
and they are all very weird and very busy,
and I decided that all my blog-ish posts about eev
would be things that they can run in a few minutes...
just like the demo that I showed a few minutes ago.
I said "like the examples in the rest of the video",
but I forgot this slide,
and I'm recording this after the demo.
So... that's it. Thanks!