Reinventing iteration, vim.NIL, empty dict, utf-8, etc. Sorry for the snark, but I'm not surprised in the slightest and have no other emotion for that. They could have that and a whole world of packages and tools out of the box by using virtually any language except Lua.
do you have any other language in mind that can be embedded into the editor like lua?
i remember that sublime text had python, but i don’t remember anything relevant from then.
Most scripting languages are embeddable. lang.exe and /usr/bin/lang are just cli frontends to lang dlls and do baseline embedding like `exit(luaL_dofile(L, argv[1]))`, which is one of Lua’s selling points until you start actually binding it to your runtime and this simplicity drowns in necessity of reinvention.
I’ve embedded Perl, Python, Lua in real projects. Didn’t touch Node.js, but pretty sure it embeds as well as long as you’re happy to deal with C++. Judging by the experience with C++ modules for node, it’s not that bad, but not that trivial either. Python, js, ts are all fine candidates with massive mature ecosystems.
Technically, all you do in embedding is: set up the interpreter, define some modules (or globals), these modules export objects or functions which are implemented in C via embedding API. Then you run scripts from strings or files. These scripts use these modules, e.g. vim .get_tab(3) .get_cur_window() .set(“filetype”, “sh”), or you can add metatable/class sugar on top of it. Nothing unique to Lua there.
Lua is small (44k), much simpler and easier to consume than python, supports multithreading, and much faster too if you consider luajit. I don't know when the neovim project adopted lua, but python got a jit this year.
The lua-users[1] website has some (rather outdated) comparisons.
It’s simpler until you need basic functionality, then it’s immediately too simple, as the link above shows. People want dicts, arrays with nil, text buffers and so on.
Multithreading in Lua is done through locking every index access (e.g. `print(t.a.b)` does four locks). It’s not that multithreading everyone wants and it is off by default behind a compile-time flag. This index-locking approach is trivial and only serves a few specific use cases. Neovim doesn’t seem to use it (because locking every “.” sucks). https://stackoverflow.com/questions/3010974/purpose-of-lua-l...
As for JIT, you have to spin few thousand times in the same loop before it kicks in. It doesn’t just magically speed things up, as it has a very noticeable upfront cost. I think it’s arguable whether this load pattern exists in a usual editor-plugin setting, maybe yes, if you e.g. implement a whole langserver in Lua. But in general, interpreter speed doesn’t matter at all for what is mostly glue code. Neovim doesn’t have its text management core written in Lua to make it matter here.
Also note that Lua is fast because its design choices allow that. Once you ignore these choices, it’s slow again. For example __newindex fires only once. To make an “active object” which always fires newindex, you proxy it via {} and it becomes pythonic. Strings are always interned, so if you work with long strings, you’re constantly recalculating hashes and trashing the heap. So you need a userdata with a buffer with a metatable and everything. Plugin code is naturally “highly embedded”, so JIT stumbles upon embedding API and stops making difference due to “exits”. It’s a very thin line to walk along even if you want that performance.
It’s the fastest scripting language and it’s easy to embed it into the application.
The ‘batteries’ can be found in `:h lua.txt`, they’ve grown significantly each release, and you can even use a package manager.