Plan.

A new programming language.

Plan is a new Lisp-based programming language. It's currently not even near finished, but you can get a taste for it with this brief introduction.

Plan is a Lisp, with all the implications of that: programs consisting of S-expressions; homoiconicity; parentheses; macros. It more closely resembles Scheme than Common Lisp, but there are elements of both -- plus features of newer Lisps like Arc. In addition, it takes ideas from languages such as Ruby, Python, Perl, and Unix shell scripting. (One goal of the language is to be a good tool for Unix programming.)

Here's a short, boring example of the language:

(deffn (make-greeter who)
  (fn (msg)
    (if (= msg 'say-hello)
          (puts "Hi, " who "!")))))
#<function make-greeter>
(make-greeter "David")
#<function>
((make-greeter "David") 'say-hello)
Hi, David!
"Hi, David!\n"

IO in Plan is inherited from Unix. There might be some macros to make this easier in the future, but here's a demonstration of the current model:

(let of (open "testfile.txt" "w")
  (puts of "Hello, world!")
  (close of))

In fact, a lot of well-known Unix operations are supported. Eventually, most useful system calls will be accessible from Plan.

Here's a simple, one-shot echo server:

(let sock (socket 'inet 'stream)
  (bind sock "" 8990)
  (listen sock 5)
  
  (let (conn ip port) (accept sock)
    (puts conn (gets conn))
    (close conn))
  (close sock))

Notice that let behaves like Arc's let, in that it only binds one variable at once. Like Arc, we have with for multiple assignment. Also see that let destructures its arguments by default. This is true of all arguments to functions, as well:

((fn (one (two three) four)
      (list one two three four)) 1 '(2 3) 4)
(1 2 3 4)

Plan also has native regular expressions, complete with their own first-class object type and syntax. You can use a regexp on its own with / as a delimiter, as long as it isn't immediately followed by a whitespace character. (That will cause the language to think that it's encountered the symbol /, which represents the division function) If you want to use / as a delimiter and start with whitespace, or you want another delimiter (it must be a punctuation character), you need only prefix it with a lower-case r. We use i, m and x as modifiers, like Ruby. Some examples:

/a regexp/
r/ a regexp/
r@a regexp@
r{a regexp}
r“a regexp”im

Notice that if you use brackets or some other balancing characters, you must use the closing equivalent punctuation character to terminate the regular expression.

The standard operations with regexps are all provided:

(regexp-match "Hello, world!" r/Hello, (.+?)/)
("Hello, world" "world")
(regexp-match "something else" r/Hello, (.+?)/)
nil
(regexp-split "split \r\n by either kind \n of newline" r/\r?\n/)
("split " " by either kind" " of newline")
(regexp-split "split \r\n by either kind \n of newline" r/(\r?\n)/)
("split " "\r\n" " by either kind" "\n" " of newline")
(regexp-subst "Hello, world!" r/Hello, (.+?)!/ "Saying hi to $1.")
"Saying hi to world."
(regexp-subst "Hello, world! Hello, world!" r/Hello, (.+?)!/ "Saying hi to $1.")
"Saying hi to world. Hello, world!"
(regexp-subst "Hello, world! Hello, world!" r/Hello, (.+?)!/ "Saying hi to $1." t)
"Saying hi to world. Saying hi to world."

Macros in Plan are unhygienic and work like Common Lisp. So you might have this:

(defmac (awhen cond &body)
  `(let it ,cond)
     (if it
       (do ,@body)))

&body is shorthand for setting the tail cdr of the formal parameters to the symbol body. It's not really shorthand, since (on most keyboard layouts) it requires the same number of keystrokes as the traditional dot notation. But it's more aesthetically pleasing, at least to my eye.

This macro is an anaphoric conditional which takes one predicate and any number of body expressions.

Gensyms in Plan are created by calling the symbol function with no arguments. Gensyms are based on random strings, instead of a globally-increasing counter, because it's safer to run things in parallel that way. At some point we may switch to a mix of randomness and counting, to be extra-safe.

(symbol)
gensym-fpfjzeflp+2eanqwuio*as-pg