In the coming posts, you may see me reference a programming language called Cobalt. Cobalt is a language I would like to create, and its design may change at any time.
Cobalt currently has a few points
1. It needs to be terse. Arc and Clojure are excellent at this, and many of the core function names will be pulled from Clojure (def, defn, ns, etc.) I will attempt to pull the function liking feature from Arc: instead of (car (cdr a)) (yes, I know there is cadr), you can use (car:cdr a)
2. It needs to have namespaces similar to newLISP and Clojure. These both allow for easy object oriented programming while remaining simple.
3. It needs to be easy. I will accomplish this by using a dual syntax.
You can define a recursive factorial function in one of two ways:
(defn (fact n)
(if (= n 1) 1
(* n (fact (- n 1)))))
This looks fine to a lisp programmer, but is not very friendly.
if(n = 1) 1
else n * fact(n – 1)]
This is more readable to most people. The syntax for this is not final, but I have some rules for it: = is an equality check. only. no ==. you define a variable with def, a function with defn, and check equality with =. And no semicolons.
5. It needs to be interpreted. I know this makes the language slower, but it allows for more dynamic code during runtime. In newLISP, you can change a function easily without macros, even while the function is being called:
(defn (bleh n) (sin n))
This makes a function list of (lambda (n) (sin n)), so we can edit the function easily without a macro: (setn (car (nth 2 bleh)) ‘cos) This will change bleh to the following function: (lambda (n) (cos n)).
Using an interpreted language frees us from having to define all variables and macros at runtime, and we can easily remove variables: (set ‘bleh nil)
6. Simple concurrency. newLISP is the golden standard for concurrency to me. It uses only three main functions to multithread: spawn, sync, and abort. But it doesn’t really multithread. It spawns a new version of itself, and lets the OS do the work. This simplicity will encourage concurrent programming.
7. A better FFI. The foreign function interface in most languages is pretty awful. From what I have heard about Java, using C functions is no fun. Racket requires one to either rewrite the C code to fit Racket, or to manually set the type of each variable going into the C functions. Once again, newLISP does this better. (import file “function”) That’s it. Granted, it may not be as safe, but it is simple and good enough to interface to C libraries with.
8. Efficiency. newLISP again. newLISP is tiny. 200 kb. That’s it. That is how it is able to perform concurrency so easily and with so little resources. It achieves this through several interesting decisions:
newLISP is dynamically scoped, which means that variables are set based on when they are set, while lexical scope, which most other languages use, has variable set based on where they are set. So if you set x globally to 1, then enter a function fn, which sets x locally to 2 and take a temporary detour to another function in the program bleh, bleh will see x as 2 if the language is dynamic, and 1 if the language is lexically scoped.
The second choice Lutz Mueller made when making newLISP was to create a different memory management system, known as One Reference Only (ORO) Memory Management. While many other elaborate memory management schemes entail marking objects for deletion and deleting all the marked objects at one time, or marking the objects with the number of times they are referenced, newLISP assumes the objects are referenced only once. They put each object on a stack, and mark them with levels of evaluation, and pop all the objects of a certain level off the top of the stack at a time. It does more reads/writes, but it is a simple scheme that allows newLISP to be efficient.
9. Less redundancy. I don’t see why there has to be 50 different ways to check the equality of two objects. It is ridiculous. newLISP, once again, uses one.
Cobalt is not in a workable state yet, but I am working on it. The first release will be based on newLISP and two modules/programs for it: the infix.lsp found in the modules folder, and the newLISP shell program seen on the website.