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...
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.2BTW your comment can be added here!KTHXBYE
Multi-line comments are wrapped with OBTW and TLDR keywords:
HAI 1.2OBTW I'm writing a comment hereand it goes here as wellTLDRKTHXBYE
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 3KTHXBYE
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 or 9000.
Float (NUMBAR type): for example, 42.0 or 3.14.
Boolean (TROOF type): WIN (which means "true") and FAIL ("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 and VAR_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 equals VAR_A minus the old value of VAR_B.
Finally, the new value of VAR_A is calculated as VAR_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_BKTHXBYE
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 MKAYANY 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 < arg2KTHXBYE
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 YARNKTHXBYE
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 longnice 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, " nameKTHXBYE
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 " MILESKTHXBYE
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 is YARN.
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_EXPRESSIONO 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 hereOIC
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 hereOIC
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 hereOIC
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 explicitlyIM 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 loopIM 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 trueIM 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 as UPPIN (increment the given VARIABLE by 1 on each iteration) or NERFIN (decrement the given VARIABLE 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.2IM IN YR cycle UPPIN YR temp WILE BOTH SAEM temp AN SMALLR OF temp AN 2 VISIBLE tempIM OUTTA YR cycleKTHXBYE
The output is:
012
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.2IM IN YR cycle UPPIN YR temp TIL BOTH SAEM temp AN BIGGR OF temp AN 2 VISIBLE tempIM OUTTA YR cycleKTHXBYE
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. Functions help organize code into reusable parts, making it easier to handle tasks like displaying localized time or performing calculations.
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 RADIUSIF 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.2HOW 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 functionIF U SAY SOKTHXBYE
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.2HOW IZ I CALCULATE_CIRCLE_PERIMETER_FOR YR RADIUS I HAS A result result R PRODUKT OF 6.28 AN RADIUS FOUND YR resultIF U SAY SOVISIBLE I IZ CALCULATE_CIRCLE_PERIMETER_FOR YR 10 MKAYKTHXBYE
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 " PERIMETERKTHXBYE
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 MKAYKTHXBYE
So, how does this program work?
We have a function, CALCULATE_FACTORIAL which accepts a number (our n) and the result.
Then, we check whether n is less than 2. If that's true, we simply return the current result and recursion stops.
If that's false, we decrement n by 1 and calculate a new result by multiplying the old result and the old n.
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!
Ilya is a lead of content/documentation/onboarding at Lokalise, an IT tutor and author, web developer, and ex-Microsoft/Cisco specialist. His primary programming languages are Ruby, JavaScript, Python, and Elixir. He enjoys coding, teaching people and learning new things. In his free time he writes educational posts, participates in OpenSource projects, goes in for sports and plays music.
Ilya is a lead of content/documentation/onboarding at Lokalise, an IT tutor and author, web developer, and ex-Microsoft/Cisco specialist. His primary programming languages are Ruby, JavaScript, Python, and Elixir. He enjoys coding, teaching people and learning new things. In his free time he writes educational posts, participates in OpenSource projects, goes in for sports and plays music.
Building an AI-powered translation flow using Lokalise API and webhooks
Managing translations in a growing product can quickly become repetitive and error-prone, especially when dealing with frequent content updates or multiple languages. Lokalise helps automate this process, and with the right setup you can build a full AI-powered translation pipeline that runs with minimal manual input. In this guide, you’ll learn how to: Upload translation files to Lokalise automaticallyCreate AI-based translation tasksUse webhooks to downloa
Build a smooth translation pipeline with Lokalise and Vercel
Internationalization can sometimes feel like a massive headache. Juggling multiple JSON files, keeping translations in sync, and redeploying every time you tweak a string… What if you could offload most of that grunt work to a modern toolchain and let your CI/CD do the heavy lifting? In this guide, we’ll wire up a Next.js 15 project hosted on Vercel. It will load translation files on demand f
Hands‑on guide to GitHub Actions for Lokalise translation sync: A deep dive
In this tutorial, we’ll set up GitHub Actions to manage translation files using Lokalise: no manual uploads or downloads, no reinventing a bicycle. Instead of relying on the Lokalise GitHub app, we’ll use open-source GitHub Actions. These let you push and pull translation files directly via the API in an automated way. You’ll learn how to: Push translation files from your repo to LokalisePull translated content back and open pull requests automaticallyWork w