(This is a really early version, which assumes you know some Lisp.)
Adder is a Lisp-1, meaning that function names are variable names,
as in Scheme. By contrast, in a Lisp-2, such as Common Lisp or Emacs
Lisp, function names are a separate namespace, so that, in the
expression (foo foo)
, the two foo
s are
unrelated. (Python also has a single namespace, while Ruby has two.
I sometimes think of Python as a Perl-1, and Ruby as a Perl-2.) All
names must be defined before being used; setting a variable without
defining it is an error. There are no Common Lisp-style packages; a
symbol is purely a name.
Adder supports object field access via Python syntax: foo.bar.baz, for example. There is also a Lispy syntax, as in (. foo bar baz), which you'll need when you want to access a field of an object that's not in a variable. In addition, .bar.baz is a function, so that (.bar.baz foo) is equivalent to foo.bar.baz. This is so you can write functional code without having to write quite so many trivial lambdas. The equivalent Lispy syntax is (.. bar baz).
All Python builtins are available as members of the object
named python
; so, for example, (python.sum '(1 2 3)) is
legal Adder.
Adder supports Common Lisp-style (defmacro).
as
or from
. For example,
(import foo bar)
is equivalent to Python's
import foo,bar
. Note that modules written in Adder can
be imported,
too—in fact, they can even be imported into Python. See
Modules, below.
(class ClassName (...ParentNames...)
...code...)
. As in Python, the class definition encloses a
block of code which is executed in class scope. For example:
(import math) (class Point () (define __init__ (self x y) (:= (. self x) x) (:= (. self y) y)) (define (dist self other) (math.sqrt (+ (* (- other.x self.x) (- other.x self.x)) (* (- other.y self.y) (- other.y self.y))))) )
(defun)
.)
(begin)
, but introduces a new lexical scope.
You probably want (let)
instead.
(extern foo)
declares that the runtime environment
will contain a variable named foo
. Used for code which
is run dynamically, relying on variables set externally (e.g., HTML
templates). Returns the value of foo
.
(begin
(defvar x 9) (exec-py "x=7") x)
will return 9, not 7, since
the x
in Adder is actually x-1
, which gets
translated into __adder__x_002d1
.
(.. bar baz)
is equivalent to (lambda (x) (. x bar baz))
.
(let)
expands into
(scope)
(define (f x) (* x x))
or (define y 9)
.
for bar in foo: yield bar(For example, if you're recursing down a tree.) In Adder, this would be
(yield* foo)
: yield all the
elements which foo would yield. In Adder, yield*
is a simple macro; in Python, it's impossible.
Modules can be written in Adder, and can be imported into Adder and
into Python. To make sure the Adder modules
in the directory /foo/bar/baz
are available, put
/foo/bar/+baz+
into sys.path
(aka the
environment variable PYTHONPATH
). If the
directory
/foo/bar/+baz+
actually exists, this won't work.
If you have a Python program, and you want to import an Adder
module, you'll need to import adder
before you import
the first Adder module; that inserts the
import hook
used to load Adder modules.
When you import an Adder module,
it gets compiled to Python; if the Adder module's source was
/foo/bar/baz/quux.+
, the
Python code is cached in /foo/bar/baz/quux.py
. At this
time, /foo/bar/baz/quux.pyc
does not get created; that
might be a nice little speedup.