LOLCODE
LOLCODE is an esoteric programming language designed to emulate the playful, pidgin-like "lolspeak" of lolcat internet memes, using humorous keywords and syntax to perform general-purpose programming tasks.[1] Created in 2007 by Adam Lindsay, a researcher in the Computing Department at Lancaster University in the United Kingdom, it emerged shortly after the rise of LOLCATS as a popular online phenomenon.[1] The language's core specification, version 1.2 released in July 2007, defines a simple procedural structure starting withHAI <version> and ending with KTHXBYE, alongside commands like VISIBLE for output and GIMMEH for input.[2] LOLCODE supports dynamic typing with six primary data types: YARN for strings, NUMBR for integers, NUMBAR for floating-point numbers, TROOF for booleans (WIN or FAIL), BUKKIT for arrays, and NOOB for untyped values.[3] Control structures include conditionals via O RLY? with branches like YA RLY and NO WAI, loops using IM IN YR <loopvar> and IM OUTTA YR, and switch statements with WTF?.[2]
Implementations such as the LOLCODE Interpreter (LCI), maintained on GitHub, allow execution of code, with additional libraries for standard I/O, strings, sockets, and utilities extending functionality up to version 1.4.[3] While primarily a novelty, LOLCODE has been used in educational contexts, including parallel computing extensions developed in 2017 to teach distributed systems concepts on supercomputers.[1] Its enduring appeal lies in blending programming fundamentals with internet humor, making it accessible for beginners exploring language design.[1]
History and Development
Origins and Inspiration
LOLCODE emerged in May 2007 as a whimsical esoteric programming language crafted by Adam T. Lindsay, a researcher in the Computing Department at Lancaster University in the United Kingdom.[4] Lindsay developed it as a lighthearted parody, drawing directly from the burgeoning lolcat internet meme that popularized images of cats accompanied by broken English captions.[1] This meme, which exploded in popularity around 2006-2007 through sites like 4chan and I Can Has Cheezburger?, featured a distinctive pidgin style—exemplified by phrases like "I CAN HAS CHEEZBURGER?"—that Lindsay sought to emulate in code syntax to inject absurdity and humor into programming.[5] The initial motivation stemmed from a desire to explore how meme culture could intersect with technical concepts, making programming appear playfully accessible while underscoring the often rigid conventions of traditional languages.[4] Lindsay first shared primitive versions of LOLCODE through three short, joke program listings on his personal blog on May 25, 2007, marking the language's informal debut as a community-driven experiment rather than a formal project.[4] By the end of that month, he launched a dedicated wiki to host the evolving specification, inviting collaborative input to foster its growth amid his limited availability.[4] Early traction built rapidly in online communities during 2007 and into 2008, fueled by shares on platforms like Digg and Reddit, where it sparked widespread amusement and discussions on esoteric languages.[4] The wiki reportedly served over a million pages in its first week of viral exposure, highlighting LOLCODE's appeal as a cultural artifact that bridged internet humor with programming curiosity, though its specification would continue to refine through community efforts in subsequent years.[4]Specification Evolution
The specification for LOLCODE originated in 2007 with the language's creation by Adam Lindsay, introducing core syntactic elements such as the program delimiters "HAI" (to initiate the code block and specify the version) and "KTHXBYE" (to terminate it), alongside basic control structures like simple conditionals and loops modeled after lolspeak phrasing.[3] Early iterations, documented as versions 1.0 and 1.1, focused on foundational syntax but left several features provisional to encourage community input.[2] Version 1.2, released as a final draft on July 12, 2007, served as the baseline for subsequent developments, incorporating refinements to variable types (e.g., YARN for strings and NUMBR for numbers), initial file creation capabilities, and modifications to flow control for greater consistency.[6] This version emphasized meme-inspired keywords while intentionally under-specifying areas like advanced loops and arrays to facilitate future compatibility.[2] Community-driven updates emerged prominently in 2008, building on version 1.2 through collaborative proposals that expanded input/output handling—such as enhancing "GIMMEH" for more robust variable input storage as YARN types—and clarifying variable scoping rules to enforce locality within functions or the main program block, eliminating global access.[7] These efforts, led by contributors including Josh Suereth and Jason Kenney, also refined loop constructs (e.g., iterative forms like "IM IN YR The version 1.3 proposals, initiated in 2007 and iteratively updated through 2008, represented the peak of active specification evolution, integrating community feedback on modern features like exception handling and variable argument lists while maintaining backward compatibility.[7] No significant revisions followed after 2010, as the creator's interest waned and community momentum shifted toward implementations rather than core changes; the specification has remained largely stable, with its canonical documentation preserved on the Esolang wiki as of 2024, affirming LOLCODE's niche as an esoteric language.[3][9]Language Fundamentals
Syntax and Keywords
LOLCODE programs are structured with a clear beginning and end, delimited by the keywordsHAI to initiate the code block and KTHXBYE to terminate it, optionally followed by a version number such as HAI 1.2.[10] Indentation is optional in LOLCODE, as whitespace is normalized to treat multiple spaces or tabs as a single space, with newlines primarily serving to end statements; however, indentation is encouraged for improved readability in longer programs.[3][10]
The language employs a vocabulary of core keywords inspired by internet "lolspeak," with variable declaration handled by I HAS A followed by the variable name, establishing it as an untyped (NOOB) entity unless assigned immediately via ITZ to set its initial value.[3][10] Assignment to existing variables uses the R keyword, as in <variable> R <expression>, allowing updates to previously declared names.[10]
Comments in LOLCODE mimic casual conversation through the BTW keyword for single-line notes placed at the start of a line or inline after a statement, with multiline comments bounded by OBTW and TLDR.[3][10] The language is case-insensitive for keywords, conventionally written in uppercase to evoke lolspeak aesthetics, while variable names remain case-sensitive.[3]
Data Types and Variables
LOLCODE supports a limited set of primitive data types, reflecting its esoteric and minimalist design. The primary types include strings, represented as YARN; signed integers as NUMBR; floating-point numbers as NUMBAR; booleans as TROOF, which can hold the values WIN (true) or FAIL (false); arrays as BUKKIT; and untyped values as NOOB.[2] Variables are dynamically typed, meaning their type is determined by the value they currently store, with an initial untyped state known as NOOB until assignment occurs. In version 1.2, BUKKIT is reserved for future expansion as an array type.[2] Variables in LOLCODE are declared using the syntaxI HAS A <variable>, where <variable> follows a naming convention that is case-sensitive, starts with a letter, and may include subsequent letters, digits, or underscores.[2] Initialization can occur simultaneously with declaration via I HAS A <variable> ITZ <value>, setting the variable to an initial value of the appropriate type; for example, I HAS A NUM ITZ 42 declares and initializes an integer variable.[2] Subsequent assignments use the reassignment operator R, as in <variable> R <expression>, which updates the variable's value and infers its new type dynamically.[2] All variables are local in scope to the enclosing block, such as a function or the main program body.[2]
Type conversion in LOLCODE is primarily automatic during assignments, where the variable adopts the type of the assigned value—for instance, assigning a string literal changes the type to YARN, while a numeric literal shifts it to NUMBR or NUMBAR as appropriate.[2] Explicit casting is achieved through the MAEK keyword, which converts an expression to a specified type, such as MAEK <variable> A NUMBR to force an integer interpretation; this modifies the variable's value accordingly, with rules like treating untyped NOOB as FAIL when cast to TROOF, or parsing numeric strings while failing on invalid inputs.[2]
The core specification of LOLCODE does not include built-in support for arrays, objects, or other complex data structures; instead, such functionality, if needed, relies on custom implementations using loops and basic variables or extensions in non-standard interpreters.[2]
Core Programming Features
Control Flow Structures
LOLCODE employs meme-inspired syntax for control flow, enabling conditional execution and iteration without traditional keywords likeif or while. These structures rely on the implicit variable IT, which holds the result of the preceding expression, evaluated as WIN (true) or FAIL (false) based on truthy or falsy values, often using TROOF type comparisons such as BOTH SAEM for equality.[2]
The primary conditional construct is the O RLY? block, which functions as an if-else chain. It begins with an expression setting IT, followed by O RLY? to initiate the block. If IT is WIN, the code under YA RLY executes; otherwise, the code under NO WAI runs as the else clause. Multiple else-if branches can be added using MEBBE <expression> between YA RLY and NO WAI, where each evaluates IT anew and executes if WIN. The block terminates with OIC to resume normal flow. This structure supports nested blocks and avoids explicit booleans by leveraging TROOF for conditions.[2]
For multi-way branching akin to a switch statement, LOLCODE uses the WTF? construct, which also operates on IT from a prior expression. It starts with WTF?, followed by one or more OMG <literal> clauses, where the block under the matching literal executes, and literals must be constants without variables. An optional OMGWTF clause serves as the default case. Early exit from the block is possible with GTFO, preventing fall-through. The construct ends with OIC. This design emphasizes exact literal matching and prohibits ranges or complex conditions.[2]
Iteration in LOLCODE is handled by the IM IN YR loop, which can create infinite or conditional repetitions. For infinite loops, the syntax is IM IN YR <label> followed by the code block and IM OUTTA YR <label> to end; exit occurs via GTFO. Conditional loops modify this with <operation> YR <var> after the label, where <operation> is UPPIN (increment by 1), NERFIN (decrement by 1), or a unary function like SUM OF, and <var> is a local temporary variable. The loop continues based on TIL <expression> (loop while FAIL, stop on WIN) or WILE <expression> (loop while WIN, stop on FAIL), with the expression using the updated <var>. The <label> is required but semantically unused. These loops support breaking with GTFO but lack built-in continue semantics.[2]
LOLCODE eschews unstructured control like goto, relying entirely on these block-based mechanisms to manage program logic in a contained, readable manner despite the humorous nomenclature.[3]
Input Output and Functions
In LOLCODE, input and output operations are handled through simple, keyword-based constructs that emphasize the language's humorous, lolspeak-inspired syntax. TheVISIBLE keyword is used for output, printing one or more expressions to standard output after implicitly converting them to strings (YARN type). It supports infinite arity, concatenating arguments with no explicit delimiters, and appends a newline by default unless the statement ends with an exclamation mark (!) to suppress it.[2] For example, VISIBLE "HELLO WORLD" outputs "HELLO WORLD" followed by a newline, while VISIBLE "HELLO" " WORLD"! outputs "HELLO WORLD" without one.[11]
Input is managed via the GIMMEH keyword, which reads a line from standard input as a string (YARN) and assigns it to a specified variable. The syntax is straightforward: GIMMEH <variable>, where the variable must be declared beforehand. This operation does not support type conversion natively; any further processing, such as parsing numbers, relies on subsequent casting or operations.[2][3] As with output, GIMMEH aligns with LOLCODE's minimalistic approach to I/O, leaving advanced handling to user-defined logic.[11]
Functions in LOLCODE promote code modularity through user-defined procedures, declared using the HOW DUZ I keyword followed by the function name and optional parameters. The syntax for definition is HOW DUZ I <function_name> [YR <param1> [AN YR <param2> ...]] <statements> IF U SAY SO, where parameters are introduced with YR and separated by AN if multiple. Arguments are passed by value, meaning expressions are evaluated and copied into local parameter variables upon invocation, supporting a fixed number of inputs without variable-length arguments.[2][3] Local scope ensures parameters do not interfere with global variables, and functions can nest within the main program or other functions.[12]
To invoke a function, use I IZ <[function](/page/Function)_name> YR <arg1> [AN YR <arg2> ...] MKAY. The number of arguments must match the definition exactly; mismatches result in runtime errors in compliant implementations. Return values are specified with FOUND YR <expression>, which exits the function and passes the evaluated expression back to the caller; if omitted, the function implicitly returns the value of the IT variable (a special placeholder for the last evaluated expression) or NOOB (null) upon reaching IF U SAY SO or using GTFO for early exit.[2][12] For instance, a function to add two numbers might be defined as:
Called asHOW DUZ I SUM YR A AN YR B I HAS A RESULT ITZ SUM OF A AN B FOUND YR RESULT IF U SAY SOHOW DUZ I SUM YR A AN YR B I HAS A RESULT ITZ SUM OF A AN B FOUND YR RESULT IF U SAY SO
I IZ SUM YR 5 AN YR 3 MKAY, it returns 8.[3]
The core LOLCODE specification lacks built-in libraries or standard modules, though implementations provide extensions for additional functionality such as strings and sockets up to version 1.4; reusable functionality like advanced mathematical operations must be implemented as custom functions within the program. This design reinforces the language's esoteric nature, encouraging self-contained code while relying on the interpreter for core execution.[2][3]
Practical Examples
Basic Programs
Basic programs in LOLCODE demonstrate the language's core structure and simple operations, serving as an entry point for understanding its syntax. These examples illustrate program initialization, output, variable handling, and basic decision-making, all within short, linear scripts that avoid advanced constructs. The language's whimsical keywords, such as "HAI" for starting a program and "KTHXBYE" for termination, encapsulate these fundamentals in a humorous yet functional manner.[3] A canonical "Hello World" program outputs a greeting to the console, showcasing the minimal setup required:HAI 1.3 VISIBLE "HAI WORLD" KTHXBYEHAI 1.3 VISIBLE "HAI WORLD" KTHXBYE
HAI 1.3: Initializes the program, specifying LOLCODE version 1.3, the current standard.[3]VISIBLE "HAI WORLD": Prints the string "HAI WORLD" to standard output, using theVISIBLEkeyword for display.[3]KTHXBYE: Terminates the program cleanly.[3]
HAI 1.3 I HAS A numbr ITZ 42 VISIBLE numbr KTHXBYEHAI 1.3 I HAS A numbr ITZ 42 VISIBLE numbr KTHXBYE
HAI 1.3: Starts the program as before.[3]I HAS A numbr ITZ 42: Declares a variable namednumbrof typeNUMBR(integer) and assigns it the value 42 usingITZ.[3]VISIBLE numbr: Outputs the variable's value, which displays "42".[3]KTHXBYE: Ends execution.[3]
NUMBR supporting integer literals for basic arithmetic precursors, though no operations are performed here.[3]
A simple conditional evaluates a boolean condition, branching output based on truthiness. For a TROOF (boolean) variable set to true (WIN), the following checks and prints accordingly:
HAI 1.3 I HAS A flag ITZ WIN flag, [O RLY](/page/O_RLY?)? YA RLY, VISIBLE "IT IZ WIN" NO WAI OIC KTHXBYEHAI 1.3 I HAS A flag ITZ WIN flag, [O RLY](/page/O_RLY?)? YA RLY, VISIBLE "IT IZ WIN" NO WAI OIC KTHXBYE
HAI 1.3: Program initiation.[3]I HAS A flag ITZ WIN: Declaresflagas aTROOFand sets it to true (WIN).[3]flag, O RLY?: Begins the conditional by evaluatingflag; the comma separates the expression.[3]YA RLY, VISIBLE "IT IZ WIN": If true, executes the "yes, really" branch, printing "IT IZ WIN".[3]NO WAI: Defines the false branch (empty here, so nothing prints if false).[3]OIC: Closes the conditional ("oh, I see").[3]KTHXBYE: Program end.[3]
O RLY? for if-else logic, with TROOF values like WIN or FAIL driving the decision, providing a foundational control mechanism.[3]
Advanced Demonstrations
To demonstrate the expressive power of LOLCODE when combining recursion, conditionals, loops, input handling, and string operations, several more complex programs illustrate practical applications. These examples build on core features to solve common algorithmic tasks, such as computing factorials recursively, accumulating sums iteratively, and generating patterned outputs through conditional string building. Each program adheres to LOLCODE specification 1.2 syntax and is limited to under 30 lines for clarity.[2]Factorial Calculator Using Recursion
A recursive factorial program defines a function withHOW DUZ I to compute n! (n × (n-1)!), using conditionals (O RLY?) for the base case (0! = 1) and recursive calls for larger values. User input is handled via GIMMEH, converted to NUMBR, and the result displayed up to a safe limit to avoid stack overflow in typical interpreters. The code is as follows:
Expected output for input 5:HAI 1.2 HOW DUZ I FACTORIAL YR N BOTH SAEM 0 AN N, O RLY? YA RLY, FOUND YR 1 NO WAI, FOUND YR PRODUKT OF N AN FACTORIAL DIFF OF N AN 1 OIC IF U SAY SO I HAS A N VISIBLE "GIMMEH N: " GIMMEH N N IS NOW A NUMBR VISIBLE SMOOSH N AN "! = " AN FACTORIAL N MKAY KTHXBYEHAI 1.2 HOW DUZ I FACTORIAL YR N BOTH SAEM 0 AN N, O RLY? YA RLY, FOUND YR 1 NO WAI, FOUND YR PRODUKT OF N AN FACTORIAL DIFF OF N AN 1 OIC IF U SAY SO I HAS A N VISIBLE "GIMMEH N: " GIMMEH N N IS NOW A NUMBR VISIBLE SMOOSH N AN "! = " AN FACTORIAL N MKAY KTHXBYE
GIMMEH N: 5
5! = 120[5] This approach has O(n) time complexity due to n recursive calls but requires O(n) stack space, which may limit it for large n (e.g., beyond 1000 in some implementations); an iterative version using loops would use constant space.[2]
Loop-Based Counter for Summing Numbers Up to N
To sum integers from 0 to n (inclusive), this program usesGIMMEH for input, initializes a counter and accumulator as NUMBR, and employs an IM IN YR loop with UPPIN to iterate, accumulating via SUM OF. The loop condition uses BOTH SAEM for equality. The code is:
Expected output for input 5:HAI 1.2 I HAS A N VISIBLE "GIMMEH N FOR SUM: " GIMMEH N N IS NOW A NUMBR I HAS A SUM ITZ 0 I HAS A I ITZ 0 IM IN YR [LOOP](/page/Loop) UPPIN YR I TIL BOTH SAEM I AN SUM OF N AN 1 SUM R SUM OF SUM AN I IM OUTTA YR LOOP VISIBLE "SUM UP TO " N " = " SUM KTHXBYEHAI 1.2 I HAS A N VISIBLE "GIMMEH N FOR SUM: " GIMMEH N N IS NOW A NUMBR I HAS A SUM ITZ 0 I HAS A I ITZ 0 IM IN YR [LOOP](/page/Loop) UPPIN YR I TIL BOTH SAEM I AN SUM OF N AN 1 SUM R SUM OF SUM AN I IM OUTTA YR LOOP VISIBLE "SUM UP TO " N " = " SUM KTHXBYE
GIMMEH N FOR SUM: 5
SUM UP TO 5 = 15[13] The loop runs in O(n time with constant space, making it efficient for moderate n (up to millions in most interpreters) and preferable over recursion for large inputs to avoid stack limits.[2]
String Manipulation: FizzBuzz Variant with YARN Concatenation
A basic FizzBuzz variant prints numbers from 1 to n, replacing multiples of 3 with "Fizz", 5 with "Buzz", and both with "FizzBuzz" viaSMOOSH for concatenation of YARN literals in the dual case. Conditionals prioritize the combined check, using MOD OF for divisibility and BOTH SAEM 0 for remainder testing. Input sets n via GIMMEH. The code is:
Expected output snippet for input 16 (first few lines):HAI 1.2 I HAS A N VISIBLE "GIMMEH N FOR FIZZBUZZ: " GIMMEH N N IS NOW A NUMBR I HAS A I ITZ 1 IM IN YR [LOOP](/page/Loop) UPPIN YR I TIL BIGGR OF I AN N BOTH SAEM 0 AN MOD OF I AN 15, O RLY? YA RLY, VISIBLE SMOOSH "Fizz" AN "Buzz" MKAY NO WAI BOTH SAEM 0 AN MOD OF I AN 3, O RLY? YA RLY, VISIBLE "Fizz" NO WAI BOTH SAEM 0 AN MOD OF I AN 5, O RLY? YA RLY, VISIBLE "Buzz" NO WAI, VISIBLE I OIC OIC OIC IM OUTTA YR [LOOP](/page/Loop) KTHXBYEHAI 1.2 I HAS A N VISIBLE "GIMMEH N FOR FIZZBUZZ: " GIMMEH N N IS NOW A NUMBR I HAS A I ITZ 1 IM IN YR [LOOP](/page/Loop) UPPIN YR I TIL BIGGR OF I AN N BOTH SAEM 0 AN MOD OF I AN 15, O RLY? YA RLY, VISIBLE SMOOSH "Fizz" AN "Buzz" MKAY NO WAI BOTH SAEM 0 AN MOD OF I AN 3, O RLY? YA RLY, VISIBLE "Fizz" NO WAI BOTH SAEM 0 AN MOD OF I AN 5, O RLY? YA RLY, VISIBLE "Buzz" NO WAI, VISIBLE I OIC OIC OIC IM OUTTA YR [LOOP](/page/Loop) KTHXBYE
GIMMEH N FOR FIZZBUZZ: 16
1
2
Fizz
4
Buzz
Fizz
...
FizzBuzz
...[14][15] This iterates in O(n) time with constant space per step, suitable for n up to 10^6; string concatenation via
SMOOSH is efficient as it handles implicit type casting from NUMBR to YARN without performance overhead in reference implementations.[2]
Implementations and Tools
Reference Implementers
The reference implementation for LOLCODE is the lci (LOLCODE Interpreter), developed by Justin J. Meza in 2010 and written in the C programming language.[16] This interpreter adheres to the LOLCODE 1.3 specification, providing full support for the language's core features, including variable declarations, control structures, and standard library modules such as STDIO for input/output operations.[16] Designed with an emphasis on correctness, portability across platforms, and execution speed, lci includes comprehensive unit tests and Doxygen-generated documentation to ensure reliable runtime behavior.[16] lci's architecture prioritizes efficiency through optimized parsing and execution, enabling it to handle complex LOLCODE programs without significant performance overhead.[16] It is actively maintained, with a stable main branch for backward compatibility and a future branch incorporating emerging features like enhanced string handling (CAN HAS STRING?) and networking support (CAN HAS SOCKS?).[16] Installation is straightforward via CMake and Make on Unix-like systems, making it accessible for developers testing or deploying LOLCODE applications.[17]
Prior to lci, early efforts included Justin Meza's initial C-based prototype, but that project was deprecated in favor of the more robust lci.[18] As the de facto standard, lci defines LOLCODE's runtime semantics and serves as the benchmark for spec compliance in the language's ecosystem.[17]