reddit / emacs

Breaking through the intermediate wall in elisp / lisps in general

Doomer1999 · 2022-12-05 08:11
I’ve been tinkering with lisps of some form since I had to learn racket a few years back in uni and have felt stuck at the point of just starting to feel comfortable with the language(s). I’ll do some advent of code problems in a lisp and things seem to go well but as soon as I get stuck it feels impossible to find a solution that makes any sense. In terms of elisp I’ll write simple functions but when digging into plug-in source code feel like there is no amount of study that could make me competent in the language. Is this just the start of the valley of imposter syndrome where you know enough to know what you’re ignorant about or the inability to make the paradigm shift to thinking in a “lispy / function” way? Not meaning to rant just curious how people broke through this barrier if anyone has felt the same.
DefiantAverage1 · 2022-12-05 10:43
Yeah, I think initially, I had no idea what was going on within package's code. But I think, personally, I learnt the most (perhaps because I was simply forced to) when I just took the leap and started writing my own packages.
Lispwizard · 2022-12-05 12:18
A trick I use when trying to understand some foreign elisp is evaluate it (m-x eval-buffer) and then use (progn (debug) <invoke the desired code>). This lets me use the debugger's d command to step into the foreign elisp, whereupon I continue using a mix of the d e, b and c commands to monitor/understand what's happening.
arthurno1 · 2022-12-05 14:07
Edebug is your good friend :). When you are curious about a function and don't really understand it, you can step through it with the debugger, eval variables, look up docs for the functions called, C-h f and C-h v for variables. Those are available immediately in your Emacs, and just a keystroke away. I recommend installing [helpful](https://github.com/Wilfred/helpful) and use it at least for a while instead of standard help or in combination. I used it *a lot* in the beginning. It will show you the source code for a function/macro, and it will also show you property list for symbols by default, so when you are learning and discovering it is really good to have those. I think I have learned more about Emacs lisp from helpful than anything else, by just seeing the code and what things do directly. Similar to functions, learn how to expand macros. You can try [macrostep](https://github.com/joddie/macrostep) too. I personally don't use it, I found it leaves my buffers often in read-only state, and I have been lazy to check why or to make a hack around. I think Elisp is very "literate", it is almost like Visual Basic, very prosa-like, but some of API calls are really arcane, and some of the design choices are a bit unconventional, if I can put it mildly so, so it can be a bit unusual and feels a little bit harder until you get into it. But once you get how things work, it is not so hard. A good idea is to create small projects and test things. I am a firm believer that programming, and problem-solving, is a skill best done by doing. So just try re-create something, or try to solve something, and experiment. As Herb Sutter says, [most experiments fail](https://www.youtube.com/watch?v=ELeZAKCN4tY), so don't be afraid to try things just to discover it is not that way it works :).
codemuncher · 2022-12-05 15:34
I have been there. There is a gap between writing config code and actually writing elisp. Might I suggest you... write some programs in elisp and learn about the different primitives and programming environment. Might I suggest you try some small functions to: \- search for a repeated regexp in a file and copy them to a new buffer \- do some other kind of text manipulation: maybe textual generation? \- write an interactive function that does something a little different? \- manipulate buffers and windows somehow? \- fork off a cli tool and control/manipulate it &#x200B; The primary entities in elisp are buffers. They are fundamental, they represent a way to store and manipulate text. And there are also "buffer-locals" whereby global configuration is stored separately for just a buffer (kind of like thread-locals, although internally elisp isnt threaded). There are many buffer locals, for example 'syntax tables', key-bindings, and much more. The info pages contain a lot of how things are done. Finally remember that at the top level, most elisp packages arent setting many variables. defcustom, defconstant are common (custom is something that can be customized!) But most of the variables are within functions. Top level variables tend to be for configuration. The flow of control and where variables and data are can be a little bit of a tricky bit at first.
github-alphapapa · 2022-12-05 22:09
Sounds like you're overthinking. Just keep writing code.
Doomer1999 · 2022-12-05 22:52
Good advice lol
AndreaSomePostfix · 2022-12-06 00:02
you can also cross pollinate with others: checkout [https://github.com/ag91/emacs-buddy](https://github.com/ag91/emacs-buddy) ;)
redguardtoo · 2022-12-06 06:10
I've answered similar question before, see https://www.reddit.com/r/emacs/comments/yuntco/comment/iwb5hx9/?utm_source=share&utm_medium=web2x&context=3 One way is to combine th cli tools and elisp to improve workflow. You can start from Gnu Grep and Gnu Find. It took me one year to master Emacs Lisp, see my github https://github.com/redguardtoo
JDRiverRun · 2022-12-07 04:43
The biggest "learning hurdle" in elisp for me over the years is the almost-but-not-quite-the-same usage of functions vs. macros. Macros sounds scary but are really just function-like things that take inputs or code and produce... other code, transforming from input to output. They do this using... the same language! (Unlike all those lame #define things in C). First, quick quiz — which of these is a macro and which is a function? (setq l (list 1 2 3)) (add-to-list 'l 4) ; function or macro? (push 5 l) ; function or macro? They look the same. They certainly don't advertise which is which. You call them the same way. They seem to do the same thing (add an element to the front of the list). But wait. One has its list argument with a single quote mark, and one doesn't. Does that matter? Why? The main distinction here is usage. Unlike functions, macros do *not* evaluate their arguments. So when you are reading elisp code, sometimes you'll see things like `(+ cnt 5)` and think: the `+` function is being handed the *value* of `cnt` (and a 5). Makes sense. Then you'll see `(cl-incf cnt)` and think, quite reasonably — this is a function being passed the value of `cnt`. But then later down in the same code you may see something like `(put 'cnt :last-val 12)`. Huh? Why did you need the apostrophe in the last case but not the second? Is this just magic? If you ask `C-h f` you will find `cl-incf` is a *macro,* while `put` is a function. The quote was there to "protect the symbol" from the evaluation that function calls do to their arguments. But even that's not too clear. Try this. Put your point after `(cl-incf cnt)` and say `M-x pp-macroexpand-last-sexp`. You will see: (setq cnt (1+ cnt)) Aha! So all these macros are just a short-hand notation that insert something simpler, something that you *probably already understand*. You will find most packages make *heavy* use of such shorthands of various types: macros, lots of macros, often piled several deep. Many of these are simple macros from "built-in" libraries, often hiding in plain sight — like `push`. You'll find many from the cl-lib (to replicate Common Lisp functionality). Others are more complex: things like `cl-defstruct` to give "named" access to data slots. Many macros are in-fact "custom-made" for the package itself. You can only understand them by reading the code and its docstrings. A key important point though: if you expanded them *all the way down*, you'd find ALL MACROS *translate* to a bunch (and I mean a BUNCH) of `let`'s and `cons`'s and `setq`'s and the like. Simple, basic stuff you know. So when you just read a complicated elisp package file cold, it may seem to you like a *different language*. And that's true; it sort of is. Macros basically explicitly incentivize you to create *custom mini-languages*. One of the richest is `cl-loop`, which is a fancy super-macro that takes various keywords and statements and makes... an amazing variety of loops. It's a language all its own. But all of it boils down to just regular old elisp. All that `pcase-let` and `destructuring-bind` stuff you see littered like crazy incantations? Macros. Just shorthand, convenience macros. With their own simple custom-designed mini "languages". So get familiar with expanding macros. Be on the lookout for them. And learn quotes: single quotes, interpolating back-quotes, etc. These are used all over the place (especially in... macros). You do *not* have to know how to write macros right away, but learning how to spot them, reason about them, and understand how they fundamentally differ from functions in-use was essential for me.
Psionikus · 2022-12-07 13:05
`elisp-index-search` always. `info-emacs-manual` only for the glossary and then after you get good at Elisp. As others say, install the helpful package. `helpful-symbol-at-point` (`describe-symbol`) will take you straight to documentation.