E's syntax is most similar to
Java, though it also bears some resemblance to
Python and
Pascal. Variables are
dynamically typed and lexically
scoped. Unlike Java or Python, however, E is composed entirely of
expressions. Here is an extremely simple E program: println("Hello, world!") Here is a recursive function for computing the factorial of a number, written in E. Functions are defined using the keyword. def factorial(n :int) :int { if (n == 1) { return 1 } else if (n > 0) { return n * factorial(n-1) } else { throw("invalid argument to factorial: "+n) } } In the first line, is a
guard that constrains the argument and result of the function. A guard is not quite the same thing as a type declaration; guards are optional and can specify constraints. The first ensures that the body of the function will only have to handle an integer argument. Without the second above, the function would not be able to return a value. Being able to see up front that information escapes out of the function is helpful for security auditing. Since E is intended to support secure co-operation, the canonical example for E programs is the mint, a simple electronic money system in just a few lines of E. The following code defines a function that makes mints, where each mint has its own currency. Each mint can make purses that hold its currency, and any holder of two purses of the same currency can securely transfer money between the purses. By quick examination of the source code, an E programmer can easily verify that only mints may change the amount of money in circulation, that money can only be created and not destroyed, that mints can only create money of their own currency, and that only the holder of a purse can change its balance. def makeMint(name) :any { def [sealer, unsealer] := makeBrandPair(name) def mint { to makePurse(var balance :(int >= 0)) :any { def decr(amount :(0..balance)) :void { balance -= amount } def purse { to getBalance() :int { return balance } to sprout() :any { return mint.makePurse(0) } to getDecr() :any { return sealer.seal(decr) } to deposit(amount :int, src) :void { unsealer.unseal(src.getDecr())(amount) balance += amount } } return purse } } return mint } Objects in E are defined with the keyword, and within the object definition, the keyword begins each method. The guard expressions in this example illustrate how to specify a value constraint (as in or ). The mint example makes use of a built-in mechanism called a
sealer. The function creates two associated objects, a sealer and an unsealer, such that the sealer can seal an object in a box and the unsealer is the only object that can retrieve the contents of the box. See the E website for a more detailed explanation of this money example. ==See also==