- It has to work. Performing a function is the entire point.
- It has to be efficient. This may involve using less time, memory, power, etc.
- It has to be maintainable. 80% of programming is debugging and updating.
What is readable code? That's partly opinion, partly experience, but also partly objective fact. "GOTO considered harmful" isn't just a meme, it was a real wake up call for the industry 56 years ago.
That brings me around to one of the main points of my programming language, Listack. I have been fascinated by stack based languages ever since I read a book on Forth way back when I was a teen. I even implemented Forth in BASIC. It was incredibly slow, but it worked. And then, a few years ago, I discovered Factor. It's a modern stack-based language. Factor lead me to Joy about the same time I discovered the False esolang. Joy has (for a programming language) a relatively large amount of well written theory behind it. False is an extremely minimal language, but it shares a lot of conceptual space with Joy. I enjoyed learning a bit about all these languages. I even implemented a False interpreter in Python.
The problem is that, like Forth, these are all write-only languages. They're efficient, they're fun, they're concatenative, and they're terrible to try to read a program of any complexity at all. But hey, at least they're not APL.
And then I started learning to program in Nim. It's a more-or-less standard high level, compiled language. It has Python-like syntax with significant whitespace (no curly braces or semicolons needed). And it has uniform function call syntax. That was a revelation for me.
That's where I got the idea for Listack. I could make a more readable stack-based language. Like most stack based languages, it would be concatenative. It would make heavy use of first-class functions and combinators. And it would be my creative contribution to the art of programming. Note how handy the immediate block (code blob) makes things.
Compare these code snippets. They all do the same thing.
style simple complex
Call: +(1, 2) func1(data1, func2(data3, data4))
Prefix: +: 1 2 func1: data1 (func2: data3 data4)
Infix: 1 + 2 data1 func1 (data2 func2 data3)
Postfix: 1 2 .+ data1 data2 data3 .func2 .func1
Concatenative style aids readability. It's easier to follow the logic when it's written left to right than when it is inside out.
inside out: func3(func2(func1(data1), data2), data3)
concatenative: data1 .func1 data2 .func2 data3 .func3
Then I added one more thing that may be genuinely unique - the single word comment. One of the major problems with powerful and efficient languages like Factor and Lisp is that they have almost no syntax. That helps the language designers and talented macro programmers, but it significantly reduces readability.
Compare these code snippets. They all do the same thing.
(truth test) {good branch} {bad branch} .if
(truth test) if {good branch} {bad branch}
if: (truth test) {good branch} {bad branch}
if: (truth test) #then {good branch} #else {bad branch}
Syntactic sugar is important for code readability.
easier to follow harder to follow
if: (test one) if: (test one)
#then {if: (test two) {if: (test two)
#then {good good} {good good}
#else {bad good} {bad good}
} }
#else {if: (test three) {if: (test three)
#then {good bad} {good bad}
#else {bad bad} {bad bad}
} }
No comments:
Post a Comment
I reserve the right to remove egregiously profane or abusive comments, spam, and anything else that really annoys me. Feel free to agree or disagree, but let's keep this reasonably civil.