Gavin as an old greybeard who has been using Emacs for almost 20 years, it's awfully encouraging to see young people using it. It's a productivity superweapon. Thanks for spreading the news.
Short explanation of 'car' and 'cdr': The original IBM machines used for Lisp had a long instruction word with an A bitfield and a D bitfield. They called the bitfields "registers", so we have CAR= and CDR=. "Address" and "Decrement" refered to the weird negative indexing that the IBM machines did. But you can think of it as just snagging one of two bitfields called A and D. The values stored in the bitfields were pointers, usually "tagged pointers".
I learned Lisp in about 1964. I liked it so much that I made my own implementation -- there wasn't one available on the only computer I had available. Nowadays I use Racket, a Lisp derivative. It's somewhat more streamlined than that first Lisp. This video really brings me back to those days. Thank you.
Thank you thank you! Such great quality and fresh videos are what Emacs deserves. Kudos, really well done! If I can suggest: the amount of keybindings in Emacs might look intimidating to newcomers. I've always thought that mentioning the commands to be run with M-x, together with the keybinding, might help seeing Emacs as more approachable.
This is a nice one, I had been wondering what the whole hash quote (#') business is all about, but never took the time to figure it out, this video cleared it up for me.
Great video! I am just now implementing an open source, cross platform text editor based on my love of Emacs and LISP, called LITE. I plan to eventually port LITE to my own OS as the built in text editor, but I have to implement dynamic linking first, which I've been procrastinating about forever :p Also, when mentioning car and cdr, I feel like it is imperative to also mention why they exist: lists are implemented as recursive pairs, meaning each value actually has a left and a right value. The nested pairs are parsed and displayed in a special syntax that is easier to read (the parenthesized list), but under the hood a 123 list should look like "(1 . (2 . (3 . nil)))". At least that's what I needed for it to click in my head. Thanks again for the amazing video!
I like the introduction, and that explanation of the name space for variables and functions. That is that symbols can have two different values. You can also use set and setf for variable and function name space for variables. There are aliases for car and cdr, which is first and rest. But there are some uses with car and cdr is usefull. For instance (car (cdr (cdr '(1 2 3 4 5)))) evaluate to 3, which is the same as (caddr '(1 2 3 4 5)) which also evaluate to 3. So you can easy combine some first (car) and rest (cdr) into one function. Another common examle is to test (cons (car '(1 2 3)) (cdr '(1 2 3))) which is '(1 2 3)
7:47 Another thing that LISP and Python have in common is support for docstrings. If the first item/statement in the function body is a string literal, then it can be displayed as help text for the function.
Thank you so much! I've been trying to learn elisp but was confused with different namespaces for functions and variables. Your videos are always awesomely useful and easy to understand!!
23:39 Having separate namespaces for functions and variables is a feature of Common LISP. If you think it makes more sense to have both in the same namespace, try the LISP variant known as Scheme.
12:13 The first implementation of LISP was on an early IBM machine. Each cell of the list fitted nicely into a single machine word, and the two halves were called the “address register” and the “displacement register” (I think). The “C” stood for “contents”, and so you can now figure out what “CAR” and “CDR” stand for.
More to your point lists are for structuring data in trees known as CONS(tructs) where the CAR is the Content of the "Address Register" and CDR is the Contents of the "Decrement Register." You can also see these sometimes referred to as the "Head" and "Tail" of the data, or the "First" and "Rest" of the data, the latter of the two makes the most sense to me.
@@c1dk1n it is lists, not trees. But lists can be arranged as trees. Yes, car can be aliased with first and cdr can be aliased to rest. And are often aliased as them. But you are right about cons, being CONStruct. That is what makes up a list, and the end is marked with an empty list (nil or ()) or a symbol. A proper list should have cons where the last is nil, but there are also constructions where it ends with a symbol.
You're very welcome! I think it comes down to how few Emacs related content creators out there and even less of those feel comfortable with elisp enough to explain it. Hopefully this video will help fill in the gaps.
Yes, Gavins videos are great for introduction and configuring Emacs and in this case Elisp. Another one I recommend is also System Crafters. Botth are great examples of content that is useful to have when one want to learn Emacs and Elisp.
6:15 Perhaps a better way to say it is that every (non-simple) LISP construct looks like “(«word» ...)” where that first «word» after the opening parenthesis determines how the rest is interpreted. Usually it’s the name of a function, but it can be a macro or some other things as well.
It is all functions, and most functions are evaluated after all the arguments are evaluated (called normal form). But some are handling the argument unevaluated (called special form). Like setq, quote, cond (original LISP only had cond, no if) if etc. That all arguments are evaluated before they are sent to the function works in most cases, but not for instance for if. (if (eq divisor 0) 0 (/ 10 divisor)) That would not worrk, because if divisor are 0, then we will get error division by zero, and not 0. So some functions are evaluating the argument themself, like the ones mentioned above. Macros are just special functions that are evaluated when reading the progams, and the result is the program that is used.
Thanks for the video, I was wondering what mapcar did. I presume one is only limited by the knowledge of lisp, as to what they can do in emacs. Hopefully yasnippet can replace my ultisnips.
that's a peculiar switch, but an interesting one, too. there is something comfy and nice about diving into old languages, i don't know if that's motivating you.
@@delibellus In my opinion, the golden age of computer science was Lisp Machine: all integrated and consistent. Unix was less well-made but less expensive so more popular and since this time, computer science did not make progress that Lisp Machine already solved. AFAIK since I'm born in 80's I did not know this age. Our generation cannot understand how our fathers' generation could succeed making expert systems combining Lisp and Prolog accessing databases of mathematical solvers that you could interact with in natural language and the system generated Fortran code and Phd-quality papers in TeX. I'm nostalgic of this epoch I have never met :)
He probably avoided it as it's different between the LISPs. Sometimes empty parens evaluate to an empty list, sometimes to nil, and sometimes those are the same thing!
This was super helpful for me. One thing I’d like to understand better is how to apply this knowledge in the maintenance of .dir-locals.el files! With Eglot, you often end up building (relatively) complex data structures, but without access to lisp - look at some of the examples for yaml-language-server and you’ll see what I mean!
8:02 I figured early on that having all those closing parentheses pile up together is not conducive to readability. So I decided to follow a formatting rule analogous to the one I use for statement brackets in C and other languages, where I put the closing parenthesis on a line by itself, at the same indent as the corresponding opener, e.g. (defun funcname (arg) (print 10) ) ; defun Sure, one line per closing parenthesis may seem excessive, but why not?
I just don't find it to be necessary and makes it easier to read larger files with the way shown in the video. I totally get people taking the same approach you do. Just figured since this is focused on teaching explaining how you can read Lisp the proper way would help in the long run. It's something people complain about before realizing it's actually better to just ignore the parens and let the indentation guide your eyes.
@@GavinFreeborn Try a larger example, and see if you still agree: (defun convert-to-region-codes (beg end) "converts alphabetic characters in the selection to “region indicator symbols”." (interactive "*r") (unless (use-region-p) (ding) (keyboard-quit) ) ; unless (let ( deactivate-mark (intext (delete-and-extract-region beg end)) c ) (dotimes (i (- end beg)) (setq c (elt intext i)) (cond ((and (>= c ?A) (= c ?a) (
@@lawrencedoliveiro9104 I personally still feel the same way. If it weren't for the extra comments I'd have a hard time even telling which open paren they relate to. I am sure I would eventually get used to it. I've just gotten used to writing and reading lisp at this point.
@@lawrencedoliveiro9104 my point was more that I wouldn't have any use for them in that case. Since it's all condensed enough I don't have to scan up and down. To be fair I am dyslexic so maybe that's why I prefer everything closer together so I don't get mixed up. Who knows
Well, we got roads, medicine, electricity, sanitation, communications, flight and the printing press, ..but I guess Emacs is up there too somewhere... 0:04
Gavin as an old greybeard who has been using Emacs for almost 20 years, it's awfully encouraging to see young people using it. It's a productivity superweapon. Thanks for spreading the news.
Comments like this warm my heart. Thank you
Short explanation of 'car' and 'cdr': The original IBM machines used for Lisp had a long instruction word with an A bitfield and a D bitfield. They called the bitfields "registers", so we have CAR= and CDR=. "Address" and "Decrement" refered to the weird negative indexing that the IBM machines did. But you can think of it as just snagging one of two bitfields called A and D. The values stored in the bitfields were pointers, usually "tagged pointers".
Thanks bro.
that is wrong. the ibm 704 did not have an address register.
it'd be better if you could also link a source or 2.
@@miko007 Quite right. It had "a register". But a portion of it was the address part.
I learned Lisp in about 1964. I liked it so much that I made my own implementation -- there wasn't one available on the only computer I had available.
Nowadays I use Racket, a Lisp derivative. It's somewhat more streamlined than that first Lisp.
This video really brings me back to those days. Thank you.
Thank you thank you! Such great quality and fresh videos are what Emacs deserves. Kudos, really well done! If I can suggest: the amount of keybindings in Emacs might look intimidating to newcomers. I've always thought that mentioning the commands to be run with M-x, together with the keybinding, might help seeing Emacs as more approachable.
This is a nice one, I had been wondering what the whole hash quote (#') business is all about, but never took the time to figure it out, this video cleared it up for me.
Great video! I am just now implementing an open source, cross platform text editor based on my love of Emacs and LISP, called LITE.
I plan to eventually port LITE to my own OS as the built in text editor, but I have to implement dynamic linking first, which I've been procrastinating about forever :p
Also, when mentioning car and cdr, I feel like it is imperative to also mention why they exist: lists are implemented as recursive pairs, meaning each value actually has a left and a right value. The nested pairs are parsed and displayed in a special syntax that is easier to read (the parenthesized list), but under the hood a 123 list should look like "(1 . (2 . (3 . nil)))". At least that's what I needed for it to click in my head.
Thanks again for the amazing video!
I like the introduction, and that explanation of the name space for variables and functions. That is that symbols can have two different values.
You can also use set and setf for variable and function name space for variables.
There are aliases for car and cdr, which is first and rest. But there are some uses with car and cdr is usefull.
For instance
(car (cdr (cdr '(1 2 3 4 5))))
evaluate to 3, which is the same as
(caddr '(1 2 3 4 5))
which also evaluate to 3.
So you can easy combine some first (car) and rest (cdr) into one function.
Another common examle is to test
(cons (car '(1 2 3)) (cdr '(1 2 3)))
which is '(1 2 3)
7:47 Another thing that LISP and Python have in common is support for docstrings. If the first item/statement in the function body is a string literal, then it can be displayed as help text for the function.
Thank you so much! I've been trying to learn elisp but was confused with different namespaces for functions and variables. Your videos are always awesomely useful and easy to understand!!
23:39 Having separate namespaces for functions and variables is a feature of Common LISP. If you think it makes more sense to have both in the same namespace, try the LISP variant known as Scheme.
Or Clojure, Hy, or any other LISP-1 :P
Thank you! Happy to see more and content about Lisp on TH-cam.
My pleasure! Happy to make it.
12:13 The first implementation of LISP was on an early IBM machine. Each cell of the list fitted nicely into a single machine word, and the two halves were called the “address register” and the “displacement register” (I think). The “C” stood for “contents”, and so you can now figure out what “CAR” and “CDR” stand for.
More to your point lists are for structuring data in trees known as CONS(tructs) where the CAR is the Content of the "Address Register" and CDR is the Contents of the "Decrement Register." You can also see these sometimes referred to as the "Head" and "Tail" of the data, or the "First" and "Rest" of the data, the latter of the two makes the most sense to me.
@@c1dk1n it is lists, not trees. But lists can be arranged as trees. Yes, car can be aliased with first and cdr can be aliased to rest. And are often aliased as them.
But you are right about cons, being CONStruct. That is what makes up a list, and the end is marked with an empty list (nil or ()) or a symbol. A proper list should have cons where the last is nil, but there are also constructions where it ends with a symbol.
@@AndersJackson Thank you for this :)
Teaching lisp with a Hawaiian shirt somehow made it even better :) Good video !
Glad you liked it! The shirt I mean 🤣
10:44 Python allows the form “(10).‗‗add‗‗(1)”. That is, an explicit method call on the object “10”.
Thanks for making this video. There seems to be a lack of tutorial videos on emacs lisp compared to things like lua for neovim, etc.
You're very welcome! I think it comes down to how few Emacs related content creators out there and even less of those feel comfortable with elisp enough to explain it. Hopefully this video will help fill in the gaps.
Yes, Gavins videos are great for introduction and configuring Emacs and in this case Elisp. Another one I recommend is also System Crafters. Botth are great examples of content that is useful to have when one want to learn Emacs and Elisp.
@@AndersJackson Yeah, System Crafters is also awesome. I am subscribed to both.
6:15 Perhaps a better way to say it is that every (non-simple) LISP construct looks like “(«word» ...)” where that first «word» after the opening parenthesis determines how the rest is interpreted. Usually it’s the name of a function, but it can be a macro or some other things as well.
It is all functions, and most functions are evaluated after all the arguments are evaluated (called normal form). But some are handling the argument unevaluated (called special form). Like setq, quote, cond (original LISP only had cond, no if) if etc.
That all arguments are evaluated before they are sent to the function works in most cases, but not for instance for if.
(if (eq divisor 0) 0 (/ 10 divisor))
That would not worrk, because if divisor are 0, then we will get error division by zero, and not 0. So some functions are evaluating the argument themself, like the ones mentioned above.
Macros are just special functions that are evaluated when reading the progams, and the result is the program that is used.
i love you, thank youfor doing this video !
You're so welcome! Great to see you liked it!
have you ever worked on Gtk+? I get an error on finding library? any Idea?
Thanks for the video, I was wondering what mapcar did. I presume one is only limited by the knowledge of lisp, as to what they can do in emacs. Hopefully yasnippet can replace my ultisnips.
Would be nice if you make more Lisp training videos :) I'm a C++ guy who wants to switch to Lisp and Prolog.
that's a peculiar switch, but an interesting one, too. there is something comfy and nice about diving into old languages, i don't know if that's motivating you.
@@delibellus In my opinion, the golden age of computer science was Lisp Machine: all integrated and consistent. Unix was less well-made but less expensive so more popular and since this time, computer science did not make progress that Lisp Machine already solved. AFAIK since I'm born in 80's I did not know this age. Our generation cannot understand how our fathers' generation could succeed making expert systems combining Lisp and Prolog accessing databases of mathematical solvers that you could interact with in natural language and the system generated Fortran code and Phd-quality papers in TeX. I'm nostalgic of this epoch I have never met :)
Awesome could we see more like this
19:10 A pair of empty parentheses is another of those constructs that evaluates to itself, so it doesn’t need to be quoted.
He probably avoided it as it's different between the LISPs. Sometimes empty parens evaluate to an empty list, sometimes to nil, and sometimes those are the same thing!
@@lens3973 Those are *always* the same thing. It’s a core LISP concept.
@@lawrencedoliveiro9104 Scheme and related dialects have #f, which is distinct from nil. e.g. (not '()) is #f for example.
@@acebulf OK, so Scheme diverges more from traditional LISP concepts than I thought.
@@acebulf that is true and false. Lisp, like C uses 0 or (), nil as false. And anything different are true. And yes, Scheme are simplified Lisp.
This was super helpful for me. One thing I’d like to understand better is how to apply this knowledge in the maintenance of .dir-locals.el files! With Eglot, you often end up building (relatively) complex data structures, but without access to lisp - look at some of the examples for yaml-language-server and you’ll see what I mean!
go push that emacs dream
I _will_ understand Lisp ... someday :)
Very Good Video, Thank You!
8:02 I figured early on that having all those closing parentheses pile up together is not conducive to readability. So I decided to follow a formatting rule analogous to the one I use for statement brackets in C and other languages, where I put the closing parenthesis on a line by itself, at the same indent as the corresponding opener, e.g.
(defun funcname (arg)
(print 10)
) ; defun
Sure, one line per closing parenthesis may seem excessive, but why not?
I just don't find it to be necessary and makes it easier to read larger files with the way shown in the video. I totally get people taking the same approach you do. Just figured since this is focused on teaching explaining how you can read Lisp the proper way would help in the long run. It's something people complain about before realizing it's actually better to just ignore the parens and let the indentation guide your eyes.
@@GavinFreeborn Try a larger example, and see if you still agree:
(defun convert-to-region-codes (beg end)
"converts alphabetic characters in the selection to “region indicator symbols”."
(interactive "*r")
(unless (use-region-p)
(ding)
(keyboard-quit)
) ; unless
(let
(
deactivate-mark
(intext (delete-and-extract-region beg end))
c
)
(dotimes (i (- end beg))
(setq c (elt intext i))
(cond
((and (>= c ?A) (= c ?a) (
@@lawrencedoliveiro9104 I personally still feel the same way. If it weren't for the extra comments I'd have a hard time even telling which open paren they relate to. I am sure I would eventually get used to it. I've just gotten used to writing and reading lisp at this point.
@@GavinFreeborn That’s why I have those comments. You couldn’t have them if they were all on the same line.
@@lawrencedoliveiro9104 my point was more that I wouldn't have any use for them in that case. Since it's all condensed enough I don't have to scan up and down. To be fair I am dyslexic so maybe that's why I prefer everything closer together so I don't get mixed up. Who knows
Well, we got roads, medicine, electricity, sanitation, communications, flight and the printing press, ..but I guess Emacs is up there too somewhere... 0:04
6:13 funciton 😄
Which mic do you use for sound input?
Just a blue Yeti
Great video!
Please make a common Lisp tutorial
Funny enough all of this also applies to common lisp 😉. I have plenty planned though don't worry
hi would you be able to link your org file in the video? it would be much appreciated
gist.github.com/Gavinok/e68a21b0e72607b20a1e0255b3aeb9fe
Here you are
My favorite drink is Jaeger
Richard Stallman would marry you
Can you turn down the treble a bit? This sounds like an ASMR video, and it annoys me so much I can’t listen to it. Thanks.
Sure I'll see what I can do 🙂
3:29 Try following the CTRL-H with “?” to get a list of all the categories of help available.
Oh that would have been worth mentioning! Thanks