caligian
Joined 3 years ago
Joined 3 years ago
The godforsaken perrenial problem of not having functions to deal with nested structures which are the bread and butter of stateful configurations, I was able to solve using nested table functions like I did in lua which made writing coherent configs much easier.
Apart from learning to use cl-labels for recursive lambdas and let-binding efficiently, I was able to quickly get productive with a custom API for stuff that does not have general-define-key and add-hook littered around. These features alongside emacs's more accessible API and baked in list and hash-table operators has made life easier. I can effectively throw around hash tables in place of alists which is what used to put me off emacs lisp but ht.el and some functions of my own greatly made me happy. Furthermore the fact that every last statement returns some value is just too good to make emacs a lisp REPL. That used to be the biggest annoyance in testing lua code for neovim functions. So I am super happy with that. The cherry on the cake for finally making a worthwhile REPL library that respects the project workspace. Now it feels right at home with a generic REPL library to use REPLs with any language as long as it has an REPL command. Similarly in contrast to neovim, emacs is lacking a code formatter plugin, similarly a vim-dispatch style plugin to quickly run predefined compile commands. After getting a grip on macros and making a use-package style macro, life became easier as now I could define formatters, compile commands all in the same place like use-package. After fiddling with gensym, I managed to make hygenic which made life easier for making future DSLs to map to objects or hash tables.
The best thing about macros is code generation in a specified way. In lua while making the API for neovim, table DSLs became a pain to write especially with all function definitions lying around and they barely looked like DSLs but deeply nested tables as they grew in depth. With macros, I can send around symbols without worrying about syntax errors. That makes things so much better when you can store code so easily instead of writing one dozen closures to store state. The biggest learning curve was the macros although I cannot proclaim that I am an intermediate at this, still a rookie but learning macros will make life with easier code generation when you can always pass around code in lists, manipulate the code and also eval them even in a function than a macro. Emacs lisp is enough competent with lua for configuration despite the lack of modules. Once you make clean functions and decide on handling only global state then it is as good as a lua module plus the able to grep all functions quickly.
So my question is this. Why are people still shitting on emacs lisp?it is a perfectly good language given lexical binding is completely useable? I suppose people look at nested alists and nested tables and for the latter. A-lists are not difficult to deal with but the constant cadr to get a value becomes quickly annoying
When you register local variables, they are merely defined as register locations and have a default value of nil which is absence and hence memory saved. They would have to mark nil explicity as a new data structure which is probably wastage as they would have to allocate memory for every variable declaration that may or may not be used.
It is just nil, nil at a literal level with the exception being local variables which are handled differently as offsets to register locations than other dynamic languages without such 'local' qualifiers.
That should explain why variables can be nil but not ta les. You can hash nils but it would take up memory. I don't think it's logical to use memory for something you are already marking as absent. Why not use false instead?
Another example is python iterators which requires a separate instance with __next__ method. It is not generic because now you can create n instances for n dicts just to use it in for syntax. Whereas in lua it is a simple closure returning the next value until nil
Something like this? You replace % with mod0()
https://github.com/caligian/lua-utils
The former uses the latter for nvim. And the latter makes lua perl with structs. We all loved perl for its lispy functions to deal with lists - grep, map, push, shift, unshift, etc. Nested ops are inspired by elixir.
My REPL fever started from a rather quaint encounter with VSCode wherein I realized that you can have a global split for an REPL which was damn cool because I did not have to fumble with opening powershell/bash in a separate window to treat scripting languages Python as a compiled language by repeatedly running the file in a different window. But the pain did not go away. It was difficult to rapidly prototype functions and still use the editor. Enter emacs and vim and their term-mode equivalents. As I was getting into learning elisp, I realized that I can use a global hash-table to track terminals mapped to their buffers. Then came the second annoyance of not having a global shell as a split window. I was stuck with 20 terminals for 20 buffers which became a pain in the ass so naturally I mapped major-modes/filetypes and voila! It solved the headache for a few years of my learning phase in programming and I was having a really good workflow of using vim/emacs and sending input to the terminals.
Fast forward to few years later where I was tired of writing nested table functions for my favorite scripting languages aka ruby, lua and Python (at that time). What was the solution? Make a library. Now this library was naturally in line with package structures which is a flat structure - source files are usually stored in subdirectories. A global REPL fails here because of constant chdir() in all REPLs causing a mess in workspace buffers. The solution? Need an REPL that automatically chdirs into workspace root so all imports work like they are supposed to with the only other solution using lua's loadfile() which is then required to be changed into a qualified import name manually. This has the additionally overwriting global namespaces over and over, so stateful APIs break while testing. Second thing to remember is that if there is not a workspace based REPL, it becomes practically useless as none of the evaled functions can be tested in the presence of other functions. This circles back to the stone age method of using two windows - one editor and another for doing the retardation of typing the same command or spamming Ctrl-n, Ctrl-p to run the same shit over and over again.
Lastly, we also need buffer-local REPLs and CWD-local REPLs if in base we are not operating in a workspace. The URL is my solution which provides everything that I mentioned. The nvim-lua equivalent is here - https://github.com/caligian/nvim-utils/blob/master/nvim-util...