Function EXpression Language

Home

Sample Code

Here are a few samples to give you a feel for the Fexl language. You can also see the full grammar here.

Hello world

print "Hello world";

String that contains quotes

Start the string with ~, then a white space character, then end it with a ~.

print ~ As Gus Baird says, "Ain't nothin' simple when you're doin' it for real."~;

String that contains quotes and tilde

Start the string with ~, then a terminator of your own choice, then a white space character, then end it with ~ followed by the same terminator. Some examples:

print ~| This string has both " and ~ characters in it.~|;
print ~~ This string has both " and ~ characters in it.~~;
print ~EOF This string has both " and ~ characters in it.~EOF;

For a real mind-bender, check out this succession of strings, where each one quotes the previous one:

print "hello";
print ~ "hello"~;
print ~1 ~ "hello"~~1;
print ~2 ~1 ~ "hello"~~1~2;
print ~3 ~2 ~1 ~ "hello"~~1~2~3;

An interactive sequence of operations

print "Hello, world"; nl;
beep; beep;    # beep the speaker twice
getline \line
print "You typed: "; print line;

Note the use of the ';' notation there. The semicolon groups everything to the right of it, effectively enclosing it in parentheses. This is known as the "pivot" notation. Without the pivot, we'd need a lot of annoying parentheses:

print "Hello, world" (nl
(beep (beep (  # beep the speaker twice
getline \line
print "You typed: " (print line I
)))))

Multi-line document

The newline after the ~ is the white space that ends the terminator. It's not part of the string itself.

print ~
My fathers sleep on the sunrise plains,
And each one sleeps alone.
Their trails may dim to the grass and rains,
For I choose to make my own.
I lay proud claim to their blood and name,
But I lean on no dead kin;
My name is mine, for the praise or scorn,
And the world began when I was born
And the world is mine to win. ...

  (Badger Clark, "The Westerner")
~;

Functions which represent True and False

\T = (\T\F T)
\F = (\T\F F)

T is the function that chooses the first of two arguments; F is the function that chooses the second. Incidentally, this is built into the standard environment so you don't have to do it yourself, but it's interesting to see how it's done.

Functions which represent lists of things

The function end is the null (empty) list. The function item H T is the list consisting of the first item H followed by the list T. So H is the "head" of the list, and T is the "tail" of the list.

\end  = (             \end\item end)
\item = (\head\tail   \end\item item head tail)

That is also built into the standard environment, so there's no need to define it yourself.

A grocery list

item "apples"; item "bread"; item "bananas"; item "toothpaste"; end

Or if you prefer it on separate lines:

item "apples";
item "bread";
item "bananas";
item "toothpaste";
end

Again, without the pivot notation, we'd need a lot of annoying parentheses:

item "apples" (item "bread" (item "bananas" (item "toothpaste" end)))

The infinite list of Fibonacci numbers

\fib == (\x\y item x; \z=(+ x y) fib y z)
\fib = (fib 1 1)

Append two lists

The append function appends two lists x and y.

\append == (\x\y x y \h\t item h; append t y)

Note that we use "==" there to indicate that append is defined in terms of itself. If we used "=", Fexl would think we meant to redefine append, replacing a previous definition with a new one, and would give us an error message because append was not previously defined.

In contrast, sometimes we want to do a series of calculations like this:

\x = (+ x y)
\x = (* z x)
\x = (- x 1)

print "x = "; print x; nl;

There we use "=" because we do mean to replace the previous definition of x at each stage of the calculation. If we used "==", Fexl would think we meant to define x in terms of itself, which in this example is nonsense.

Reverse a list

The reverse function reverses a list. It uses an auxiliary function reverse_onto which takes the list along with a stack which is initially null. That function pushes each element of the list onto the stack, returning the final value of stack as the reversed list.

\reverse_onto == (\stack\list
    list stack \head\tail reverse_onto (item head stack) tail)

\reverse = (\list reverse_onto end list)

Interestingly, you can even eliminate the appearance of a couple of those parameters, using what is called the "point-free" style. That also allows us to use a ';' in one spot, and while we're at it, we'll put the first function on a single line.

\reverse_onto == (\stack\list list stack \head reverse_onto; item head stack)
\reverse = (reverse_onto end)

The two versions are functionally equivalent, and the syntactic difference is a matter of preference. Compressions like this can either help or hinder comprehension, so use good judgment.

Divide two arbitrary-precision natural numbers

Here we represent natural numbers in binary notation, as a list of bits (T or F). This is a highly advanced function, so don't expect to understand it at first glance, but it is interesting that it can be done in so few lines of code. It's surprisingly fast given that it's doing everything as pure lambda expressions. Of course, for heavy-duty arithmetic operations you'll probably want to use a built-in Big Number library.

# (div x y) divides x by y, returning the quotient q and remainder r which
# satisfy: x = q*y + r and 0 <= r < y.  Or if y=0, the function returns q=0 and
# r=0.
#
# NOTE: The function (nat b n) is the natural number b + 2*n, where b is a
# bit and n is a natural number.

\div == (\x\y\return
    x (return 0 0) \bx\nx
    y (return 0 0) \by\ny
    by
        (
        # divide by odd
        div nx y \q\r
        \r=(nat bx r)
        sub r y \ok\d
        return (nat ok q) (ok d r)
        )
        (
        # divide by even
        div nx ny \q\r
        return q (nat bx r)
        )
    )

2011-12-13