-
Couldn't load subscription status.
- Fork 0
Tutorial
So you want to learn Fig? That's great! Just follow this tutorial and you'll be a Fig whiz in no time.
Here is Fig's version of the customary Hello, World!:
"Hello, World!"
This is simple, right? Right. This is the golfiest solution, right? Wrong. There are at least two things you can do to this to make it shorter:
- Closing quotes are not required if they are at the end of a line. The code now becomes
"Hello, World!(Try it online!) - As in many other golfing languages, there is a method of string compression. Unlike normal strings, compressed strings start with a
D(they still end with a quote).
The final form of the Hello, World! program becomes:
D'!>N]JyR
Where the D begins the string, '!>N]JyR is the compressed form of Hello, World!, and the closing quote is omitted. There is a third way of making this shorter, but that I will leave until we get to the niladic operator section.
Fig uses a functional, prefix code paradigm. Prefix is easy to understand: all operators come before their arguments. For example, instead of saying 1 + 1 = 2, you would say = 2 + 1 1. Simple, right? Functional is slightly harder to understand. In this section I will attempt to explain the functional programming paradigm.
The functional programming paradigm is defined by Wikipedia as:
Functional programming is a programming paradigm where programs are constructed by applying and composing functions. It is a declarative programming paradigm in which function definitions are trees of expressions that map values to other values, rather than a sequence of imperative statements which update the running state of the program.
Basically, instead of writing
a = int(input("Type a number:"))
a = a + 3
print("You number plus three is:", a)
you would write
print("Your number plus three is:", int(input("Type a number:")) + 3)
In the syntax of the Lisp family of functional languages, the above statement would become
(print "Your number plus three is:" (+ (int (input "Type a number:")) 3))
Note how the names are the functions are moved into the parentheses, and spaces replace commas. Note also how the + operator has been demoted (promoted? :P) to a function, like everything else. This is the style used by most derivatives of The One Functional Programming Language That Started It All™, Lisp.
Fig is basically a heavily shortened Lisplike. First, I removed all the spaces I could. This is actually perfectly legal in most Lisplikes. Then I shortened the function names to one character:
(p"Your number plus three is:"(+(i(?"Type a number:"))3))
This is basically tinylisp. As I did not want to make a language identical to another, I went further. Just how much parenthesization can be removed? As I found out, the following can still be correctly parsed:
p"Your number plus three is:"+i?"Type a number:"3
This, is what the syntax of Fig is all about.
A Fig program fundamentally consists of two elements: function calls and constants. Functions have something called "arity", which is simply the number of arguments the function has. There are certain terms for certain arity functions: a "niladic" function takes no arguments, a "monadic" function takes one argument, and "dyadic" and "triadic" functions take two and three arguments, respectively. Some functions take a variable number of arguments; those are called "variadic" functions. The argument lists are ended with a ). All functions in Fig return exactly one value.
Constants are what they say they are: a constant value. In Fig, there are three constant types: strings, numbers, and function references. A string is text enclosed in quotes:
"This is a string"
As mentioned before, you can omit the closing quote at the end of a file. There are also compressed strings, which are simply a shorter version of normal strings. If you need a single character string, you can use /. /A is the string "A".
Numbers are simply written as numbers: 12345. Decimal literals are also supported: 123.456. If you wish to write two numbers in a row, put a space between them:
1234 12345.678
Leading zeros are parsed as separate numbers. Function literals will be discussed later.
When parsing a program, Fig attempts to satisfy all the arity requirements of the operators (Fig's builtin functions) it encounters. For example, assuming a is monadic and b is dyadic, Fig will parse the program ba12b13 as
(b (a 12) (b 13))
and not
(b (a 12)) (b 13)
If an arity requirement cannot be met, the parser will insert implicit inputs.
Fig has four data types: strings, numbers, lists, and functions. Like other functional languages, functions are first-class objects, and can be passed around and used like other data types. We already saw how to write strings and numbers, so let's take a look at how to look at how to write the other two.
There is no dedicated list syntax in Fig, but there are operators that construct lists. The principal one is the variadic operator `:
`1 2 3 4 "abc" 5.6)
Here, the variadic operator ` takes a variable number of arguments, ending with a ). This code will construct the list [1, 2, 3, 4, "abc", 5.6]. There are two more list-constructing operators: W takes one argument and returns a single-element list, and w takes two arguments and returns a two-element list. There is also : that makes a two-element list with one argument.
There are two ways to write function literals in Fig. One is '. It is technically a monadic operator that returns a function reference to its argument. The code '+1 will return a function that, when called, calls +1. The other one is @. @ returns a function reference to the next operator. @+1 is parsed as @+ 1. The function, when called, will call +, not +1.
Comments are written using #, a space after, and they continue to the end of the line. #abc is not a comment, but # abc is.
I/O is similar to I/O in other languages: it is implicit. As mentioned before, implicit input is taken is there are not enough arguments to satisfy the arity of the operator. Input can also be taken explicitly, with the niladic operator x. To demonstrate implicit input, consider the following program:
+
As the + operator does not have enough arguments given to it, this program is equivalent to
+xx
Input is cyclic: the first time input is obtained the first input is given, the second time the second input, etc. If, for example, the input operator is invoked for the fourth time and there are only three inputs, the first input will be given again. The fifth time, the second input, and so on. It is also contextual: invoking it in the program gets the program's input, and invoking it in a function gets the function's input. To get the program's input regardless of context, use #x. You can also get the full input list using #X.
Output is also implicit. The last value returned is the value that is printed. This typically means the leftmost function. You can also explicitly print using the monadic operator ,. That operator prints with a trailing newline. If you do not need a trailing newline, use ; for printing instead.
Being a functional language, list manipulation is well supported by Fig. The three main methods of manipulation are mapping, filtering, and reducing.
Mapping in Fig is done with the M operator. It takes any object and a function, and maps the function over the object. Here is a simple example:
M`1 2 3 4 5)'*+
Let's dissect this. First, you can see that M is invoked on the list [1, 2, 3, 4, 5] and on the function (evident by the ') *+. The operator applies the function on every element of the list, and returns a new list with the changed elements. In this case, the function first adds the number to itself, them multiplies it by itself. 1 is turned into ((1 + 1) * 1) 2, 2, into ((2 + 2) * 2) 8, etc. The end result is the list [2, 8, 18, 32, 50].
TBC