The festive season is upon us, and I think it’s the perfect time to have some fun! Today, I would like to give the gift of a LOLCODE tutorial which explains how to get started with this esoteric language for feline fanatics. Basically, LOLCODE language emerged as a funny experiment and it’s based on an Internet meme called “lolcat”. This meme is an image macro that usually features a cat and some funny text. The text often contains intentional grammar mistakes — it is called “lolspeak” (sometimes, “catspeak”). Some popular lolcats include Grumpy Cat, Longcat, and Serious Cat.
So, if lolspeak exists, lolcode should too, right? You betcha! Effectively, LOLCODE was inspired by catspeak and was introduced by Adam Lindsay in 2007. This language does not have a clear definition but still it is possible to write relatively complex programs using it. Therefore, in this post I will guide you through this language and show various usage examples. One thing to note, though: this language was created for fun only and it is by no means ready for production use. Still, it is even possible to create a simple webserver with it…
The source code can be found on GitHub.
Installing LOLCODE interpreter
So, to get started we will need an interpreter to run our scripts. In this tutorial we are going to use lci
— a LOLCODE interpreter written in C language. First of all, download the latest release from GitHub and unpack the archive. Then, the steps will vary depending on your operating system.
Installing LOLCODE on Linux and Mac
To install the interpreter on Linux or Mac systems, you’ll need CMake and Python 2.7+. CMake should already be present on Linux, and Python is usually available on all *nix systems.
Then simply run the following command:
./install.py --prefix="/home/username/opt"
This is going to install lci
in the /home/username/opt
directory. That’s it!
Installing LOLCODE on Windows
Unfortunately, Windows does not provide the required build tools out of the box, so you will need to do the following:
- Install Python 2.7+ and make sure it is added to your
PATH
. - Install MSYS2 by following instructions on the official website.
- Open
msys2.exe
and run the following command:pacman -S base-devel msys2-devel cmake
to install all the necessary tools. - Change directory to the
lci
folder and runcmake .
and thenmake && make install
.
Alternatively, you can simply use Repl.it online IDE which supports LOLCODE as well.
LOLCODE basics
The basics of LOLCODE are nicely summarized in the official documentation. In this section we are going to discuss the most important concepts and also explore some examples.
Creating and running the files
Programs written in LOLCODE should have a .lol
extension. Each file should be opened with a HAI
instruction followed by the language number (we are going to be using version 1.2). After this instruction you can write the actual code.
The file should be closed with a KTHXBYE
command. Here’s an example:
HAI 1.2 ...your code here... KTHXBYE
To run a program, use the following command:
lci /user/path/my_script.lol
On Windows, you’ll need to run this command from the MSYS2 terminal.
Comments
To add a single-line comment, use the BTW
keyword:
HAI 1.2 BTW your comment can be added here! KTHXBYE
Multi-line comments are wrapped with OBTW
and TLDR
keywords:
HAI 1.2 OBTW I'm writing a comment here and it goes here as well TLDR KTHXBYE
Working with variables
To work with a variable, you have to declare it first using the I HAS A
statement followed by the name of your variable. Then you can assign some value to it by employing the YOUR_VARIABLE R YOUR_VALUE
construct. For instance:
HAI 1.2 I HAS A my_num my_num R 3 BTW my_num is now equal to 3! KTHXBYE
In the above example we’re creating a new variable called my_num
and then assigning a value of 3
to it. Note that we’ve also added indentation for the main code block, but this is not required and does not have any special significance to the interpreter.
You can declare a variable and assign a value to it in one go by adding ITZ YOUR_VALUE
after the declaration:
HAI 1.2 I HAS A my_num ITZ 3 KTHXBYE
Variables can contain data of the following types:
- String (
YARN
type): for example,"cat"
,"this is a string"
,""
(empty string). Note that strings support interpolation:"My name iz :{NAME} and age iz :{AGE}"
. - Number (
NUMBR
type): for example,42
or9000
. - Float (
NUMBAR
type): for example,42.0
or3.14
. - Boolean (
TROOF
type):WIN
(which means “true”) andFAIL
(“false”).
If a variable does not have any value upon declaration, it is considered to be untyped (NOOB
type). Finally, note that LOLCODE uses dynamic typing; therefore, you don’t have to provide types manually.
Naming your variables
In LOLCODE, the variable naming guidelines are quite simple:
- The variable name must begin with a letter.
- The variable name can contain letters, numbers, or underscores.
- You cannot use dashes or any other special characters when naming your variables.
- You can use letters in lowercase or uppercase, or a combination of both. Remember, in any case, that variable names are case sensitive.
Variables scope
Also note that in LOLCODE there are no global variables. The variables are either local to the main block of your program, to the current function, or to the cycle. Finally, you cannot access a variable before its declaration.
Using operators
Next, let’s talk about the operators LOLCODE supports. At first, operators may seem awkward because they are written in the prefix format, for example:
SUM OF 1 AN 2 BTW it simply means 1 + 2
The AN
keyword is not required when using unary operators. Now let’s take a look at some of the operators LOLCODE has to offer.
Mathematical operators
SUM OF
— addition.DIFF OF
— subtraction.PRODUKT OF
— multiplication.QUOSHUNT OF
— division.MOD OF
— integer division.BIGGR OF
— maximum of two numbers.SMALLR OF
— minimum of two numbers.
Note that if both arguments are integers (NUMBR
), then the result will also be an integer. If one of the numbers is a float (NUMBAR
) though, then the result will be a float as well. Finally, the interpreter will try to automatically cast your arguments to numbers, thus the following program is correct:
HAI 1.2 I HAS A my_num ITZ 3 QUOSHUNT OF my_num AN "2" KTHXBYE
If the argument cannot be cast, an error will be raised.
Some practice
Let’s write a small program to swap two variable values (represented as integers) without using the third variable. The algorithm is quite straightforward:
- We have two variables
VAR_A
andVAR_B
. - First, we calculate the sum of the two values and store it in the first variable
VAR_A
. - Then, the new value of
VAR_B
equalsVAR_A
minus the old value ofVAR_B
. - Finally, the new value of
VAR_A
is calculated asVAR_A - VAR_B
.
Let’s implement the above logic with LOLCODE:
HAI 1.2 I HAS A VAR_A ITZ 5 I HAS A VAR_B ITZ 10 VAR_A R SUM OF VAR_A AN VAR_B BTW 15 VAR_B R DIFF OF VAR_A AN VAR_B BTW 5 VAR_A R DIFF OF VAR_A AN VAR_B BTW 10 VISIBLE "VAR_A: " VAR_A VISIBLE "VAR_B: " VAR_B KTHXBYE
VISIBLE
outputs the given text to the terminal. We will discuss this operator in more detail later.
Nice!
Boolean operators
Next, let’s take a look at the boolean operators:
NOT
— unary negation.BOTH OF
— “and”.EITHER OF
— “or”.WON OF
— “xor”.ALL OF
— “and” but with an infinite arity (effectively meaning you can provide as many arguments as needed).ANY OF
— “or” with an infinite arity.
Please note that when using an operator with an infinite arity, you have to provide the MKAY
keyword at the end of the statement:
ALL OF arg1 AN arg2 AN arg3 MKAY ANY OF arg1 AN arg2 AN arg3 MKAY
Comparison operators
To compare two values, use one of the following operators:
BOTH SAEM
—==
.DIFFRINT
—!=
.
Problem is, there are no operators like “greater than” or “less than”, so you will have to use the following idiom:
HAI 1.2 I HAS A arg1 ITZ 5 I HAS A arg2 ITZ 6 BOTH SAEM arg1 AN BIGGR OF arg1 AN arg2 BTW arg1 >= arg2 DIFFRINT arg1 AN BIGGR OF arg1 AN arg2 BTW arg1 < arg2 KTHXBYE
The idea is that first you find the maximum (or a minimum) number and then compare the result with the first argument. More information can be found in the official docs.
Concatenation
To perform string concatenation, use the SMOOSH
operator. It has an infinite arity:
HAI 1.2 VISIBLE SMOOSH "lol " AN "cat " AN "rulez!" MKAY BTW this will produce "lol cat rulez!" KTHXBYE
Type casting
Finally, let’s see how to explicitly cast types. In order to do that, use the MAEK
operator: MAEK YOUR_EXPRESSION A TYPE
. Note that here we should use the A
keyword, not AN
. The TYPE
can have one of the four values listed above (for instance, TROOF
).
HAI 1.2 I HAS A my_num ITZ 42 MAEK my_num A YARN KTHXBYE
In the example above we’re converting the integer 42
to a string (YARN
).
Also, you can recast a variable using the MY_VARIABLE IS NOW A TYPE
statement, like so:
my_num IS NOW A YARN
Okay, so we have covered the basics of LOLCODE, now let’s discuss slightly more advanced concepts.
Working with input and output
Output
So, to print something to the STDOUT
(standard output, which is effectively your terminal), you would use a VISIBLE
operator. It has an infinite arity and does not have to be closed with MKAY
:
HAI 1.2 I HAS A name ITZ "longcat" VISIBLE "my " "name iz " name " and I'm long" VISIBLE "nice to meet " "ya" KTHXBYE
The output of the program above will be:
my name iz longcat and I'm long nice to meet ya
The VISIBLE
operator converts all arguments to YARN
(string) automatically. It also adds a carriage return character \n
to the end of the string but you can suppress it by providing a !
symbol at the end of the statement:
HAI 1.2 I HAS A name ITZ "longcat" VISIBLE "My " "name iz " name " and I'm long."! BTW note that I've added a ! symbol here VISIBLE " Nice to meet " "ya." KTHXBYE
In this case you’ll see the following output:
My name iz longcat and I'm long. Nice to meet ya.
Input
To get an input from the user, utilize the GIMMEH
operator followed by a variable name:
HAI 1.2 I HAS A name VISIBLE "Plz enter yer name:" GIMMEH name VISIBLE "Hey, " name KTHXBYE
Please note that GIMMEH
always converts the entered value to YARN
.
For instance, we can create a program to convert kilometers to miles. One mile is roughly 1.6 kilometers, which means we have to perform a simple division:
HAI 1.2 I HAS A KILOMETERS I HAS A MILES VISIBLE "Plz enter number in kilometers:" GIMMEH KILOMETERS KILOMETERS IS NOW A NUMBAR MILES R QUOSHUNT OF KILOMETERS AN 1.6 VISIBLE "Yer number of miles iz " MILES KTHXBYE
So, this script works in the following way:
- We ask the user to enter a number in kilometers.
- Next, we have to convert this value to
NUMBAR
(float) because initially its type isYARN
. - After that, calculate the number of miles which equals to kilometers divided by
1.6
. - Finally, output the result to the screen.
Conditionals
Now we’ll look at how to create conditional statements. The overall approach is quite simple. You start by creating an expression and then providing an O RLY?
statement on the next line:
YOUR_EXPRESSION O RLY?
Do note, though, that O RLY?
can be provided on the same line. In this case you have to add a comma after the expression:
YOUR_EXPRESSION, O RLY?
After that, provide YA RLY
(true branch) and NO WAI
(false branch) statements. Finally, close the code block with OIC
:
YOUR_EXPRESSION, O RLY? YA RLY BTW true branch goes here NO WAI BTW false branch goes here OIC
Additionally, you can provide an “else-if” branch which is written as MEBBE
followed by an expression:
YOUR_EXPRESSION, O RLY? YA RLY BTW true branch goes here MEBBE ANOTHER_EXPRESSION BTW else-if goes here NO WAI BTW false branch goes here OIC
Case statements
Apart from “if-else” logic, LOLCODE also supports case statements. They start with an expression followed by a WTF?
statement:
EXPRESSION, WTF?
After that, you can provide as many comparison blocks as needed, each starting with an OMG
keyword. Please note that the comparison block must be a unique literal (the number of literals is unlimited). There is also the option to provide an OMGWTF
statement acting as a fallback. Finally, close the statement with the OIC
keyword:
EXPRESSION, WTF? OMG CONDITION1 BTW the first block goes here OMG CONDITION2 BTW the second block goes here OMG CONDITION3 BTW the third block goes here OMGWTF BTW the fallback goes here OIC
You can also provide a GTFO
statement inside any of the OMG
blocks, which immediately exits the current WTF?
statement:
EXPR, WTF? OMG COND1 VISIBLE "COND1" GTFO BTW this statement means "immediately exit the current WTF? block" OMG COND2 VISIBLE "COND2" OMG COND3 VISIBLE "COND3" OIC
Loops
Infinite loops
Now, let’s see how to create loops with LOLCODE. To create a simple loop, use the below code:
IM IN YR loop_label BTW this is the body of the loop BTW this loop will go on forever until stopped explicitly IM OUTTA YR loop_label
loop_label
simply marks the start and the end of the loop and is not used inside the loop itself. Note that in the example above we’ve created an endless loop because it does not have any exit conditions or explicit exit statements. To exit the loop, use GTFO
:
IM IN YR loop_label BTW this is the body of the loop BTW this loop will go on forever until stopped explicitly GTFO BTW this statement exits from the loop IM OUTTA YR loop_label
While loops
However, it is also possible to create “while” or “until” loops with slightly more complex code:
IM IN YR cycle ACTION YR VARIABLE WILE EXPRESSION BTW this loop will run while the given EXPRESSION is true IM OUTTA YR cycle
This is a “while” (WILE
) loop that will run while the given expression is true (WIN
). A couple of things to note:
- The
ACTION
can be any unary function, as well asUPPIN
(increment the givenVARIABLE
by 1 on each iteration) orNERFIN
(decrement the givenVARIABLE
by 1). - The
VARIABLE
is temporary and local to the loop. It should not be declared explicitly. - You can utilize the
VARIABLE
inside the expression.
For example, let’s create a WILE
loop that has three iterations and increments the temporary variable by 1 on each iteration:
HAI 1.2 IM IN YR cycle UPPIN YR temp WILE BOTH SAEM temp AN SMALLR OF temp AN 2 VISIBLE temp IM OUTTA YR cycle KTHXBYE
The output is:
0 1 2
In this example, we iterate temp
by 1 (initially its value is 0) on each iteration. The loop runs while temp
is less than or equal to 2
. Once this condition becomes false (FAIL
), we exit the loop.
Until loops
So, you can create until loops in pretty much the same way as while loops. The only difference is that you need to say TIL
, not WILE
:
HAI 1.2 IM IN YR cycle UPPIN YR temp TIL BOTH SAEM temp AN BIGGR OF temp AN 2 VISIBLE temp IM OUTTA YR cycle KTHXBYE
In this instance, the loops run until temp
is greater or equal to 2
.
Functions
The final topic I’d like to discuss is the use of functions in LOLCODE.
Defining functions and returning values
The function definition starts with a HOW IZ I
statement followed by a function name. Then, you can provide an optional list of arguments by saying YR ARGUMENT1 AN YR ARGUMENT 2 ...
. Then provide the body of your function and finally close the definition with IF U SAY SO
:
HOW IZ I CALCULATE_CIRCLE_PERIMETER YR RADIUS VISIBLE PRODUKT OF 6.28 AN RADIUS IF U SAY SO
In this example, we’re creating a function to calculate the circle perimeter using the formula 2 * PI * Radius
. 2 * Pi
is roughly 6.28
, therefore we take this number and multiply it by radius.
To return a value, use FOUND YR EXPRESSION
. To return with no value (NOOB
type), say GTFO
:
HAI 1.2 HOW IZ I CALCULATE_CIRCLE_PERIMETER_FOR YR RADIUS FOUND YR PRODUKT OF 6.28 AN RADIUS BTW this will return radius * 6.28 GTFO BTW this would simply exit from the function IF U SAY SO KTHXBYE
Calling functions
To call a function, use I IZ
statement followed by the name of your function and the optional list of arguments YR ARGUMENT1 AN YR ARGUMENT 2 ...
. Close the statement with the MKAY
keyword:
HAI 1.2 HOW IZ I CALCULATE_CIRCLE_PERIMETER_FOR YR RADIUS I HAS A result result R PRODUKT OF 6.28 AN RADIUS FOUND YR result IF U SAY SO VISIBLE I IZ CALCULATE_CIRCLE_PERIMETER_FOR YR 10 MKAY KTHXBYE
So, in this instance we are calculating the perimeter of a circle using the given radius and then outputting it to the screen. Of course, we can further enhance this program:
HAI 1.2 HOW IZ I CALCULATE_CIRCLE_PERIMETER YR RADIUS I HAS A RESULT BOTH SAEM RADIUS AN 0, O RLY? YA RLY, GTFO NO WAI RESULT R PRODUKT OF 6.28 AN RADIUS FOUND YR RESULT OIC IF U SAY SO I HAS A RADIUS I HAS A PERIMETER VISIBLE "GIMME YER RADIUS:" GIMMEH RADIUS RADIUS IS NOW A NUMBR PERIMETER R I IZ CALCULATE_CIRCLE_PERIMETER YR RADIUS MKAY PERIMETER IS NOW A YARN VISIBLE "YER PERIMETER IZ " PERIMETER KTHXBYE
Here we are asking the user to enter the radius value and then convert it to NUMBR
. Next, we call the function and check whether the radius is equal to 0. If yes — exit from the function immediately with GTFO
. In this case, the result value will have a NOOB
type which cannot be implicitly converted to YARN
(string) when printing the result on the screen. To fix this issue, we explicitly convert PERIMETER
to YARN
. If the radius is not zero, we calculate perimeter as before and return the result.
Recursion
Lastly, let’s see how to write recursive functions in LOLCODE. As an example, we are going to calculate the factorial of a given number. Remember that the factorial for n
is calculated as n * (n - 1) * (n - 2) * ... * 3 * 2 * 1
. Also, the factorial of 0!
is 1
, while the factorial for negative numbers is undefined (but for simplicity we’ll assume it also equals to 1
).
HAI 1.2 HOW IZ I CALCULATE_FACTORIAL YR FACT_NUMBER AN YR RESULT DIFFRINT FACT_NUMBER AN BIGGR OF FACT_NUMBER AN 2, O RLY? YA RLY, FOUND YR RESULT OIC I HAS A NEW_FACT_NUMBER I HAS A NEW_RESULT NEW_FACT_NUMBER R DIFF OF FACT_NUMBER AN 1 NEW_RESULT R PRODUKT OF RESULT AN FACT_NUMBER FOUND YR I IZ CALCULATE_FACTORIAL YR NEW_FACT_NUMBER AN YR NEW_RESULT MKAY IF U SAY SO I HAS A FACT_NUMBER VISIBLE "GIMME YER NUMBER:" GIMMEH FACT_NUMBER FACT_NUMBER IS NOW A NUMBR VISIBLE "YER RESULT " I IZ CALCULATE_FACTORIAL YR FACT_NUMBER AN YR 1 MKAY KTHXBYE
So, how does this program work?
- We have a function,
CALCULATE_FACTORIAL
which accepts a number (ourn
) and the result. - Then, we check whether
n
is less than2
. If that’s true, we simply return the current result and recursion stops. - If that’s false, we decrement
n
by1
and calculate a new result by multiplying the old result and the oldn
. - Next, we call the same function again with a new
n
and a new result. - Outside the function we ask the user to enter a number and convert it to
NUMBR
type. - Finally, we call our recursive function and print its result to the screen.
Great job!
Conclusion
So, in this post we had some fun and discussed LOLCODE — an esoteric language for cat lovers. Of course, this language is not ready for production use, but it could be interesting to rewrite some your existing programs with LOLCODE as an experiment. That’s it for today, folks! Wishing you a Happy Christmas, and until the next time!