fif - An Introduction

Introduction

fif has been granted the first production version as of May. 27, 2018, so this blog post is going to be a light interactive introduction to the language. But first things first, what is fif?

fif is a stack-based scripting language in clojure(script). It is:

  • Stack-oriented
  • Interpreted
  • Easily Extensible
  • Simple
  • Sandboxed

Let's get like Yoda, shall we!

Interactive-Repl Get

To improve the interactivity of this blog post, I created a interactive fif repl. You can manipulate the code in-place, and the changes will be evaluated instantly, displaying the contents of the main stack and the contents of the standard output while you type.

You can find the code for it here.

As a first example, i'm going to write the famous "Hello World" to standard output

"Hello World!" println _

Go ahead and try changing println to str/upper-case or try changing "Hello World!" to a different string, and you should see the preceding Main Stack and Standard Output sections change accordingly.

May the Forth be with you

fif takes a lot of its concepts from Forth, which is most notably one of the first stack-oriented programming languages. In order to program in a stack-oriented language, you first need to place values on the stack, and special values, called word definitions manipulate the values that were previously placed on the stack.

fif supports all values defined in the EDN Format Specification, which consists of all clojure data types.

2 ;; Integers

3.14 ;; Floats

:some-keyword ;; Keywords

a-symbol? ;; Symbols

{:a "a" :b "b"} ;; Maps

[1 2] ;; Vectors

(:a :b) ;; Lists

Several symbols have been defined as word definition functions in order to perform operations on stack values. The most common word definitions to learn about are the arithmetic operations.

1 2 +

1 1 -

2 2 *

3 2 /

The arithmetic word operations take two values off the stack, and push the result of those two values back onto the stack.

By chaining these stack operations together, you can use fif as some sort of advanced calculator.

1000 12 / 20 + 2 * 12 - print

But besides basic arithmetic, fif has a wealth of other word functions at your disposal. If only there was an easy way to learn about them...

Developing through self-discovery

fif has a set of word functions used specifically for self-discovery. I'll be going over each of the more useful ones so that you can begin exploring.

see

see is probably the most important repl function in fif. To explain what it does, let's see what see does...

see see

see provides information on whatever value comes after it. Go ahead and try replacing see see with see + or see pr to get information on what they are, and what they do.

see-words

see-words provides a way to get a glimpse at every word definition in the current fif stack machine.

see-words

This word definition was taken from Forth, and given the overwhelming amount of information, it makes it difficult to learn anything in particular about fif. Fortunately there are other word operators that are far more useful.

see-groups

If you've already been using see, you probably noticed that word definitions have an assigned group.

see-groups lists every group present within the fif stack machine. Note that word definitions that are part of the standard library have groups that are prefixed with stdlib.

see-groups

Want to see what words make up a particular group? The next section covers that.

dir

dir is used to show what word definitions make up a particular group.

dir :stdlib.repl

The results of dir :stdlib.repl appears to show variants on see-words and see-groups called see-user-words and see-user-groups. All of the standard library word definitions are specially defined so that these repl variants can provide information on user-defined word definitions.

Defining New Word Functions

fif allows you to define new word functions. It wouldn't be that useful as a scripting language, otherwise.

;; doc add2 "( n – n ) Add 2 to the top value."

;; group add2 :arithmetic

fn add2

2 +

endfn

_ 2 add2

_ see add2

In this example, the word function add2 was created, which simply adds 2 to the top value. More importantly, you can see that it appears as a word function when using the see word operator.

You'll also note that two lines were left commented at the top of the repl code section. As an exercise, feel free to uncomment these lines to see what effect it has on the output.

Defining New Word Variables

fif has two types of variables at your disposal. Their uses are based on whether you define them in a word function or not.

The first type of variable is a global variable, which is defined statically with def, and programmatically using setg

;; Define a global variable statically

def cat-fact-1 "A group of cats is called a clowder."

_ ;; Display our cat fact

cat-fact-1 println

_ ;; Change our cat fact programmatically

*cat-fact-1 "Cat Fact Missing" setg

_ cat-fact-1 println

The second type of variable is a local variable. Local variables are defined statically with let, and programmatically using setl.

Local variables are dynamically scoped within function declarations, which makes them a great way to generate function arguments from the stack.

def x "Global Variable X"

def y "Global Variable Y"

_ doc add "( x y – n ) Add top two values together."

fn add

;; Create locally scoped function arguments

*y swap setl

*x swap setl

_ ;; Function Body

x y +

endfn

_ 1 2 add

_ x println

y println

In the variable examples, a new concept was introduced. Any symbol that includes a pointer symbol, *, infront of it has the pointer symbol removed, and is placed on the stack without being evaluated. This is refered to as Word Referencing, and it is required in order to define variables programmatically. I would also like to note that Word References can be stacked by preceding the symbol with ever more pointer symbols.

def x 10

_ x *x **x ******x

_ *x 20 setg

_ x *x **x ******x

Introductory Taste Test Complete

So far, i've covered:

  • Using fif for basic arithmetic
  • Finding pre-existing word functions and word variables in a fif stack machine.
  • Defining new word functions and word variables in a fif stack machine.
  • An interesting cat fact

In my next blog post, i'll be covering conditional forms, conditional loops, and the functional operators.

But... I want to know more!

If you would like to learn more about fif, and what it has to offer, the github page goes more in-depth into most of the standard library operators, and also explains how to extend and use fif in your clojure(script) projects.

There is also an online fif playground which contains scripts expressing the many things you can do in fif. I will be covering each of these in later blog posts.

Whale, that's it

If you feel like I've missed something, or you wish to exchange facts, you can find me on the clojurians slack as @benzap.


Related Resources