|
with respect to winestock's account of the 'lisp curse', i think he's wrong about lisp's difficulties. he's almost right, but he's wrong. lisp's problems are somewhat social but mostly technical basically in software there's an inherent tradeoff between flexibility (which winestock calls 'expressiveness'), comprehensibility, and performance. a glib and slightly wrong way of relating the first two is that flexibility is when you can make software do things its author didn't know it could do, and comprehensibility is when you can't. bugs are deficiencies of comprehensibility: when the thing you didn't know your code could do was the wrong thing. flexibility also usually costs performance because when your program doesn't know how, say, addition is going to be evaluated, or what function is being called, it has to check, and that takes time. (it also frustrates optimizers.) today c++ has gotten pretty far in the direction of flexibility without performance costs, but only at such vast costs to comprehensibility that large codebases routinely minimize their use of those facilities comprehensibility is critical to collaboration, and i think that's the real technical reason lisp programs are so often islands dynamic typing is one example of these tradeoffs. some wag commented that dynamic typing is what you should use when the type-correctness of your program is so difficult to prove that you can't convince a compiler, but also so trivial that you don't need a compiler's help. when you're writing the code, you need to reason about why it doesn't contain type errors. in c, you have to write down your reasoning as part of the program, and in lisp, you don't, but you still have to do it, or your program won't work. when someone comes along to modify your program, they need that reasoning in order to modify the program correctly, and often, in lisp, they have to reconstruct it from scratch this is also a difficulty in python, but python is much less flexible in other ways than lisp, and this makes it much more comprehensible. despite its rebellion against curly braces, its pop infix syntax enables programmers inculcated into the ways of javascript, java, c#, c, or c++ to grasp large parts of it intuitively. in lisp, the meaning of (f g) depends on context: it can be five characters in a string, a call to the function f with the value g, an assignment of g to a new lexical variable f, a conditional that evaluates to g when f is true, or a list of the two symbols f and g. in python, all of these but the first are written with different syntaxes, so less mental processing is required to distinguish them in traditional lisp, people tend to use lists a lot more than they should, because you can read and print them. so you end up with things like a list of a cons of two integers, a symbol, and a string, which is why we have functions like cdar and caddr. this kind of thing is not as common nowadays, because in common lisp we have defstruct and clos, and r7rs scheme finally adopted srfi-9 records (and r6rs had its own rather appalling record system), although redefining a record type in the repl is pretty dodgy. but it's still common, and it has the same problem as dynamic typing, only worse, because applying cadr to the wrong kind of list usually isn't even a runtime error, much like accessing a memory location as the wrong type in forth isn't this kind of thing makes it significantly easier to get productive in an unfamiliar codebase in python or especially c than in lisp 40 years ago lisp was vastly more capable than the alternatives, along many axes. smalltalk was an exception, but smalltalk wasn't really available to most people. both as a programming language and as a development environment, lisp was like technology from the future, but you could use it in 01984. but the alternatives started getting less bad, borrowing lisp's best features one by one, and often adding improvements incompatible with other features of lisp as 'lightweight languages' like python have proliferated and matured, and as alternative systems languages like c++ and golang have become more expressive, the user base of lisp has been progressively eroded to the hardest of hardcore flexibility enthusiasts, perhaps with the exception of those who gravitate to forth instead. and hardcore flexibility enthusiasts sometimes aren't the easiest people to collaborate with on a codebase, because sometimes that requires them to do things your way rather than having the flexibility to do it their own way. so that's how social factors get into it, from my point of view. i don't think the problem is that people are scratching their own itches, or that they have less incentive to collaborate because they don't need other people's help to get those itches thoroughly scratched; i think the social problem is who the remaining lisp programmers are there are more technical problems (i find that when i rewrite python code in scheme or common lisp it's not just less readable but also significantly longer) but i don't think they're relevant to octo |
I'll skip discussing Python for the moment because I think there are a lot of things wrong with it. If I try, we'll be here forever, but they mostly come down to not enough consistency and it being pointless to discuss for reasons which will become clear below.
Whatever the nature of the cause/effect of the LISP ecosystem, I see Octo's issues as similar in result:
1. There is no way to load and persist useful data in any popular CHIP-8 variant
2. Once people get a taste, the lack of IO means they do one of two things:
3. They few who stay in Octo or CHIP-8 are interested in writing their own tools, libraries, and ISA variantsKeep in mind, I still see this as success. This is based on my understanding of the Octo author's post saying farewell to running OctoJams[1] and my time as a participant. It got me interested in assembly and has helped many other people learn and begin to use low-level tools.
Compare this to Uxn:
* Although flawed, it has useful IO capabilities
* People have built applications which they use to perform real work every day
* An already-familiar ecosystem of tools exists to cater to the interests of similarly-minded people
> 40 years ago lisp was vastly more capable than the alternatives, along many axes. smalltalk was an exception, but smalltalk wasn't really available to most people. both as a programming language and as a development environment, lisp was like technology from the future, but you could use it in 01984.
Yes, I think that's getting at what I mean. One of the motivating factors for 100r was that Xcode is bad fit for people who live on a boat with solar-powered computers. So are Visual Studio or PyCharm.
Although the Uxn ecoysystem is far from optimal, it's still better than those heavy IDEs. Better yet, it was already mostly here a few years ago. Even to this day, it feels like it's from some point(s) in a better timeline where the world wasn't full of leftpad/polyfill/AI or whatever the next ridiculous crisis will be.
In other words, Uxn is a pidgin[2] of ideas "solarpunk" or even just small, understandable computer types like. At the same time, it does this without too much purism holding it back:
* Simple enough and familiar enough mish-mash of forth and low-color, plane-based display
* Low enough power that its cheaper than Xcode to run without more effort
* Enough IO capabilities to get things done
Since it already had all of this as of a few years ago, it's had time for social effects to take off. For example, you can share a picture, a music track, or text made using Uxn-based software. Those files will still work even if the Uxn spec evolves in backward-incompatible ways again. Its design choices are also inherently good for (or limited to) producing art aligned with the aesthetics of the creators. That seems to be part of a self-reinforcing popularity loop at this point.
Although it's theoretically possible to make similar things using CHIP-8 based tools, nobody bothers. Even if you record the output of music sequencers which have been written for it, you can't really save your work or load in data from elsewhere. In theory, there's the 16 bytes of the persistent state registers in XO-CHIP which could be repurposed from a calculator-like thing into IO, but the fact I'm mentioning it should underline the main issue in that community: purity concerns. Those limit it more than having "real" 16 buttons do. Yes, you could do some interesting multiplexing or even just bit-shift every other button press to make a pretend terminal-like keyboard, but the purity focus inadvertently kills interest more than silly function pointer syntax.
Decker is the complete opposite of Octo in this. It also goes even farther than Uxn in giving up purity concerns. Sure, it's complicated and inefficient, but it is inherently built around sharing widgets with others in a mishmash of HyperCard and Web 1.0 revival spirit:
1. You can make gifs with it, and this is probably its most popular use in the form of Wigglypaint[3]
2. When asked "um, can I borrow source from it?", the answer is "Absolutely!"[4]
This is why as much as certain Python projects frustrate me, I'm not trying to fix their inherent Python-ness right now. I just accept they're what they are. As you pointed out, it's better than the alternatives in many cases. Before you ask, I won't go as far as calling JavaScript is good, but I'll admit it's shareable. :P
[1]: https://en.wikipedia.org/wiki/Pidgin
[2]: https://beyondloom.com/blog/octojam.html
[3]: https://internet-janitor.itch.io/wigglypaint
[4]: https://itch.io/post/10183760