Fool is an esoteric programming language created by User:DigitalDetective47. Its name comes from the common abbreviations func and bool, which are the only concepts that the language defines. It also references the fact that anyone who would attempt use this language for anything productive is a fool.
Data is stored on a tape of bits that extends infinitely in both directions. The tape is initially filled with 0s.
A program is read as a list of function definitions separated by newlines. Programs must not include a trailing newline. The syntax for a function declaration is:
<function name>:<function code>
Any function name that does not contain any of
&().:| or newlines is valid. This means that the empty string is a valid function name. A function name may not be declared multiple times within a single program. Every function takes a bit as input and returns a bit as output. There are three built‐in functions in Fool. First is
<, which moves the tape head one cell to the left. It returns its input as its output. Second is
>, which move the tape head one cell to the right, copying its input to its output. Third is
*. If its input is 1, it flips the bit pointed to by the tape head. It then returns the value of the bit pointed to (after flipping), regardless of its input. There are three special operators that combine two functions together. All operators of the same precedence bind right to left. Most binding is
., which is a function composition. It takes the input to its expression and passes it to the expression bound on the right. It then passes the output from the expression bound on the right and passes it as the input to the expression bound on the left. It then returns the output of the expression bound on the left. (
h:g.f defines as .) Less binding are
|, which act as a binary AND and OR, respectively. Both sides are given the expression's input, and they both use lazy evaluation right‐to‐left. For example, define
h:g&f. The process for evaluating is:
- Evaluate and store the result as .
- If , return 0. Otherwise, evaluate and return .
Parentheses can be used to change the order of binding. As an example of the default operator binding,
a.b|c.d&e.f|g.h is parsed as
(a.b)|((c.d)&((e.f)|(g.h))). To get
((a.b)|(c.d))&((e.f)|(g.h)), the simplest form would be
(a.b|c.d)&e.f|g.h. To get
(a.b)|((c.d)&(e.f)|(g.h), the simplest form would be
a.b|(c.d&e.f)|g.h. When the program is run, the
main function is called with an input of 1, and its output is ignored. A program without a function called
main is invalid. All implementations must reject invalid programs.
Writes the ASCII representation of the string onto the tape.
H:>.>.>.>.*.>.>.>.*.> e:>.*.>.>.*.>.>.>.*.>.*.> l:>.>.>.*.>.*.>.>.*.>.*.> o:>.*.>.*.>.*.>.*.>.>.*.>.*.> ,:>.>.>.*.>.*.>.>.*.>.> :>.>.>.>.>.>.*.>.> w:>.*.>.*.>.*.>.>.*.>.*.>.*.> r:>.>.*.>.>.>.*.>.*.>.*.> d:>.>.>.*.>.>.>.*.>.*.> !noshift:*.>.>.>.>.>.*.>.> main:!noshift.d.l.r.o.w. .,.o.l.l.e.H
To pass a 0 as input, run the program as‐is. To pass a 1 as input, append
.* to the last line to set cell 0 to 1.
stepLeft:*.<.*.>|stepLeft&*.< glideLeft:glideRight&stepLeft stepRight:*.>.*.<|stepRight&*.> glideRight:glideLeft&stepRight main:*.(glideRight.<.*.*.>.*|*)
Trivial recursive version
Fool can be proven to be Turing-complete as BitChanger can be compiled into it, with the omission of I/O, which is not required for Turing-completeness. First, reverse the program, and replace each square bracket with its opposite (
[). The non‐looping functions are easy to define:
>|*.*.>.*. Each bracketed block can be separated into its own function:
<some unique name>:<.>|<some unique name>.<code>&*.<.*.*.>.
- Official interpreter (The output form used is not part of the specification and is not required for any implementations.)