Ideal Software Language
The Ideal Software Language in my mind has the following attributes.
People should be able to learn the syntax, the full syntax, in less than 10 minutes. It should be a simple matter to write a full parser and lexer. The number of rules should be extremely few. All aspects of the syntax should be commonly used, with no rare edge cases. The syntax should be natural, limiting the amount of non-alphanumeric characters to where they are absolutely necessary.
Unification of Macros and Functions
Macros are neat, but really, why are they separate from functions? Think of the code as going through the following lifecycle:
- Developers writes code
- The code generates more code thanks to the compiler. There may be multiple compiler steps to get to the final code, with optimizations and such applied on the way.
- The code the compilers generates is interpreted by a machine (virtual or otherwise).
- The program itself will write code as part of its normal operation that needs to be compiled and run as well.
Where does macros, or for that matter, functions fit in? They are only abstractions. Really, macros are functions that generate code. So let's treat them like functions that generate code, and not something else entirely.
Don't get me wrong, macros are a powerful idea. But let's not pretend that it is something more than functions that generate code.
One of the common problems in a language is that it is hard to talk about the language itself in the language. For instance, it is easy to say "add a and b together" in any language. But how many languages make it easy to say, "the expression that says add a and b together"? This is a core critical function in all languages, and not having it makes life hard.
When you start quoting, you are going to confuse yourself by what you mean by identifiers within the quote. Some identifiers are purely internal, referring to things only in the quote. Others are external, referring to things outside of the quote. The external ones have two varieties as well, ones that are intended to be substituted before the quoted expression is rendered, and ones that are intended to be substituted after the quoted expression is rendered. Let me give you an example.
Sufficient Base Type System
The language has to have the following basic types to be any use at all.
- long integers, that is integers that can grow to any size, depending on the limits of memory on the system.
- text characters or glyphs.
- text strings.
- Arrays of stuff, anything.
- Sets of stuff, anything.
- Hashmaps of stuff, anything.
- Other types that the language requires.
My proposal is a language that consists of only expressions. Each expression is either:
- An atom, which is an identifier or a literal.
- Identifiers are pretty much anything you want to use, are case-sensitive. They mean whatever that identifier is set to mean in that environment where the identifier is actually evaluated.
- Literals are literal strings or literal numbers, including integers, floats, and decimals. These mean what those literals mean, and their value can never change.
123 123.345 "A literal string of text"
- A grouped set of atoms, surrounded by parentheses and separated by whitespace. This means to call the function in the first item with the parameters of the rest of the items in the list.
This is pretty much the syntax of a basic Lisp or scheme language.
There are a few additions to make quoting easier.
A quoted expression returns a list with the items preserved exactly as they were specified.
A template expression allows you to substitute in values evaluated in the context where the expression is defined.
(set 'this-is-evaled 123) '(a &this-is-evaled b) => '(a 123 b)