Everything about the language is to be defined in the language itself. The language is to be fully extensible by users, with no magic constructs that are built-in and not replicable as user-defined extensions. Of course to be implementable this requires bootstrapping.
Emphasize cleanliness, readability, flexibility, and extensibility.
Memory management is too important for both safety and performance to be left in the hands of programmers.
Define as much as possible by the binding of names to values. There is only one namespace, with static nesting of scopes.
Discourage assignment, and make it syntactically obvious where it is allowed or occurs. But do not forbid it.
For similar reasons, use constant (aka immutable) data structures primarily, but also allow for variable (aka mutable) versions of most data structures.
Discourage unnecessary type declarations, but allow them where needed. Most type information can easily be inferred by the compiler.
Use hygienic macros pervasively.
Language-enforced access control is incompatible with macros and with debugging within the language, so do not attempt to provide that type of feature. Use naming conventions and social enforcement instead.
Arithmetic operations must always produce mathematically correct results or an error signal. No insanity like (x + y) / 2 is sometimes a negative number when both x and y are positive.
Strive for programs to be readable yet concise. Hence use infix syntax, case-insensitive names, and nesting structure indicated by indentation rather than punctuation.
Minimize the use of punctuation and maximize the use of whitespace, for readability.
Avoid abbreviation, but when you must abbreviate, do it consistently.
Anything that must be intrinsically known to the compiler is explicitly marked.
Strive for simple concepts that combine in powerful ways. Keep removing unnecessary complex features until no more can be removed.
Take full advantage of classes and methods.
Do not conflate the concepts of class, module, scope, and encapsulation. Use simple concepts that combine in powerful ways instead of one overly powerful concept that tries to do everything.
;; Construct an integer from a string in any base between 2 and 36 (default base 10) def integer(s string, named: base = 10 2..36) ;; Get the digit value of a character, assuming ASCII (Unicode) encoding def digit(char '0'..'9') char.code - '0'.code def digit(char 'A'..'Z') char.code - 'A'.code + 10 def digit(char 'a'..'z') char.code - 'a'.code + 10 def digit(char) 999 ; force error("'$char' is not a digit in base $base") ;; Parse optional leading sign and digits def result := 0 integer def sign := false def digits := false for char in s if char = '-' and not sign sign := -1 else if char = '+' and not sign sign := +1 else def dig = digit(char) if dig < base result := result * base + dig else error("'$char' is not a digit in base $base") sign := sign or 1 digits := true ;; Assemble the answer if digits result * sign else error("\"$s\" does not contain any digits")