Skip to content
DevMeme
6186 of 7435
A Developer's Awkward Introduction to Lua's Infamous Quirks
Languages Post #6784, on May 23, 2025 in TG

A Developer's Awkward Introduction to Lua's Infamous Quirks

Why is this Languages meme funny?

Level 1: An Unexpected Outburst

Imagine you’re proudly introducing your best friend to something you really love — say, a pet parrot you’ve trained to “talk.” You’ve been bragging about how polite and amazing this parrot is. But when your friend finally visits to see the parrot perform, the bird suddenly squawks out a weird, embarrassing phrase instead of the nice greeting you taught it. You freeze and blush, and your friend gives you a confused, slightly judgmental look, as if to say, “Uh… that’s what you were excited about?” In this meme, Lua (a programming language) is like that parrot with an unexpected outburst. The person in blue is the proud owner showing off their “pet” language, and the little drunken character is Lua behaving oddly at the worst moment. The odd things it blurts out – “We count from one! Everything is a table!” – are like the parrot’s embarrassing squawk. To put it simply, the meme feels funny because it’s about loving something that also has a silly quirk. It captures that awkward but comic feeling when you say, “Isn’t this the best!” and the thing you’re showing does something that makes you go, “Heh, okay, that was weird… let me explain.” Even if you don’t know programming, you can laugh at the situation: a friend showing off something and then having to face-palm because their favorite thing just got a bit out of control, like a tipsy friend at a party blurting out secrets.

Level 2: Lua’s Quirky Basics

Let’s break down the joke in simpler terms, focusing on the LanguageFeatures and why they’re peculiar. Lua is a lightweight scripting language often used in video games and embedded systems (for example, to script game behaviors or configure applications). It’s known for being fast, simple, and easily embedded into larger programs (like a game engine). However, it has some uncommon LanguageQuirks that can surprise developers used to other languages:

  • Arrays start at 1: In Lua, when you create a list (array), the first element is accessed with index 1. This is called one_indexed_arrays (one-indexed arrays). For example, if you have a Lua table like scores = {100, 200, 300}, then scores[1] would be 100 (the first score), and scores[3] would be 300 (the third score). Many popular languages like C, Java, Python, or JavaScript use 0 as the first index (zero-indexing), meaning you’d normally expect array[0] to be the first item. Because Lua goes against this convention, newcomers might accidentally do scores[0] expecting to get 100, but scores[0] in Lua would actually be nil (no value) since nothing is stored at index 0! This off-by-one difference is a classic LanguageGotcha — a little difference that causes bugs or confusion if you’re not aware of it. In programming humor, off-by-one errors (mistakes where a loop runs one time too few or too many, or an index is off by one) are extremely common. So a language that intentionally uses a different indexing base can feel like a prank. Imagine a for loop that goes through an array: in Lua you’d write for i=1, #scores do ... end whereas in many other languages you’d do for (int i = 0; i < length; i++ ). If you forget and start at 0 in Lua, your loop misses the first element – oops! Developers find this simultaneously frustrating and amusing, hence it’s prime material for a TechHumor meme.
  • Everything is a Table: Lua’s primary (almost only) complex data type is called a table. A table in Lua is a very flexible structure: it can work like an array (list of things indexed by number), like a dictionary or map (keys and values), or even like an object (storing properties and methods). In many languages, you have distinct data types for these concepts (like arrays vs. objects in JavaScript, or lists vs. dicts vs. classes in Python). But in Lua, they decided to keep the language minimalist – one data structure to rule them all. For example:
    -- Lua example
    person = { name = "Ada", age = 29 }        -- a table with string keys, acting like an object
    print(person["name"])     -- Outputs: Ada
    numbers = {10, 20, 30}                  -- a table with implicit numeric keys, acting like an array
    print(numbers[1])       -- Outputs: 10  (first element, since indexing starts at 1)
    
    In Lua you could even mix types: mix = { "hello", isLua = true } is a valid table with a numeric index 1 holding "hello" and a key "isLua" holding true. This flexibility is powerful, but it’s different from the structured approach other languages use. When the little creature in the meme yells “Objects? Everything is a Table,” it’s joking about how if you ask Lua for any sort of complex container or object, the answer is always “Use a table for that!” It’s as if the language doesn’t distinguish between a list and an object – they’re the same thing internally. For veteran Lua developers, this is normal and even elegant in its simplicity. But to someone new, it sounds like a lazy or drunken answer: “we didn’t bother adding real objects, just reuse tables for that too!” It also leads to some DeveloperHumor moments: for instance, if you accidentally treat an object like an array or vice versa, you might get weird results (because tables don’t stop you – they’ll happily let you do person[1] or numbers["name"] even if that doesn’t really make sense, often resulting in nil). A junior developer might scratch their head at a bug like “why is this table length 0?” not realizing they used a non-numeric key by mistake and Lua isn’t counting that in the length.

Now back to the comic’s scenario – why is it funny or RelatableDeveloperExperience? The blue-outlined character is basically a developer who loves Lua, showing it off to a friend (the blank-outlined character). This friend likely comes from a more mainstream programming background. The blue character says proudly, “This is my favorite scripting language!” and points to Lua (with its logo on a “storefront” in the comic). The friend initially is willing to check it out, but then Lua’s little “mascot” (portrayed as a slightly drunk little creature) stumbles out and blabbers the unusual facts: “Objects? Everything is a Table, Arrays start at 1.” This is exactly what the friend finds strange:

  • The friend’s face in panel 3 shows a flat, unimpressed look. In tech terms, the friend is doing a mental LanguageComparison and thinking “How is that a good thing? That sounds inconvenient.” Perhaps they recall how in languages they use daily, arrays always start at 0 and objects are a separate concept. The friend might even be aware of the potential for mistakes (like off-by-one errors or the difficulty of modeling complex data with just tables).
  • Meanwhile, the blue Lua fan is sweating (the few sweat drops drawn on the blue figure) — that’s the language_fanboy_embarrassment kicking in. He’s in the hot seat because his favorite language just revealed its weird side. This is a relatable moment: maybe you boasted about how great your tool or language is, but then have to sheepishly add, “...oh, and you have to remember this odd rule.” It’s like showing off a super-cool gadget and then saying “but uh, you have to crank it twice before it starts.”

The categories and tags clue us in that this is DeveloperHumor. It plays on a shared understanding among programmers: pretty much every programming language has at least one thing that others find weird or annoying. Here, Lua has two big ones on display. If you’ve been around different languages, encountering one-indexing can truly feel like visiting a country where everyone drives on the opposite side of the road. It’s not wrong, but your reflexes scream that it is! Similarly, “everything is a table” is like being told forks and spoons don’t exist separately, and you must eat everything with a spork – again, not necessarily bad (sporks are handy!) but definitely unusual if you grew up using distinct cutlery.

For a junior developer or someone new to Lua, the meme is highlighting these features so they understand why a demo might go sideways:

  • If you don’t know about the 1-index rule, you might run a Lua script in front of others and the results shift by one position (e.g., printing the wrong element of an array). Cue confusion and a quick fix on the spot—an awkward situation in a live presentation.
  • If you try to explain Lua’s data model enthusiastically (“It has tables that can do everything!”), some might interpret that as a lack of structure or rigor. The comic exaggerates this by making the “table” concept sound like a drunken rant. It’s poking fun at how we often defend our favorite tech’s odd design decisions with a slightly forced smile, hoping the audience just trusts us that it’s fine.

In summary, Level 2 explanation makes it clear: the meme is about LanguageFeatures of Lua (specifically one-indexed arrays and using tables for all data structures) and how those can cause moments of RelatableHumor for developers. You don’t need deep Lua experience to get it – just knowing that “most languages start counting at 0, but Lua starts at 1” and “Lua basically only has one compound data type (table)” is enough to appreciate why the friend in the comic is skeptical. Anyone who’s tried to convince friends to try a new programming language or framework will recognize the nervous sweat when that friend finds a weird quirk. The meme is essentially saying: Lua is awesome, but yeah... it has some explaining to do. And as a viewer, whether you’ve used Lua or not, you likely chuckle because you’ve been on one side of this conversation or the other during your developer journey.

Level 3: Off-by-One Culture Shock

At the highest level, this meme lampoons the Lua programming language’s quirky design choices that catch even experienced developers off-guard in serious demos. The blue character excitedly says “THIS IS MY FAVORITE Scripting Language,” but the moment of truth is spoiled by Lua’s drunken oddball behavior: its one-indexed arrays and “everything is a table” philosophy. To a seasoned developer, this scenario is painfully familiar. It’s that moment when you’re evangelizing a technology you love—be it Lua, Perl, or JavaScript—only for its infamous LanguageGotchas to burst in uninvited, like an inebriated mascot blurting out embarrassing truths. Here, the tiny creature with a bottle represents Lua’s unique features barging into the conversation unfiltered. It shouts, “Objects? Everything is a Table, Arrays start at 1,” which is exactly the kind of line that makes a LanguageFanboy sweat nervously in front of a skeptical colleague.

Why is this so relatable among developers? Because we’ve all witnessed (or committed) scripting_language_evangelism that goes awry due to such quirks. Imagine a senior programmer proudly demonstrating a game engine modding script in Lua (Lua is popular in game development for its lightweight embedding). Then mid-demo, an indexing_off_by_one_culture shock happens: the code is off because Lua lists start at index 1 instead of the 0 that almost every other language uses. The unimpressed friend’s side-eye in panel 3 says it all: “Seriously? Counting from 1? What is this, 1970?” It’s an industry in-joke that arrays in most languages (C, Java, Python, etc.) start at 0, so encountering one that doesn’t feels like stepping into an alternate universe.

The humor is amplified by the DeveloperExperience_DX perspective: A developer championing their favorite tool must either gloss over or justify these odd design decisions. Lua’s LanguageQuirks are endearing to its veteran community (some love the simplicity of one data structure and 1-based indexing because it aligns with human counting and old math conventions), but to outsiders these features sound like the language had a few too many drinks. The “drunk mascot” metaphor indicates Lua’s quirks causing chaos at the worst time, much like a tipsy friend embarrassing you at a professional event. RelatableHumor comes from that shared pain: no matter how much we adore a technology, it likely has at least one LanguageFeature that’s awkward to explain to others (imagine a Python fan being asked about the infamous IndentationError, or a JavaScript dev cringing at NaN === NaN being false). Here it’s Lua’s turn under the spotlight for its LanguageGotchas:

  • Arrays start at 1: This often leads to subtle bugs when developers forget Lua isn’t zero-indexed. In a demo, an off-by-one bug can crash the entire wow factor. Seasoned devs joke that “off-by-one errors” are among the classic blunders (along with releasing on a Friday). Using a language where indexing is shifted by one feels like voluntarily inviting that blunder. The meme’s friend character effectively represents the critical colleague thinking “this will cause an off-by-one bug, mark my words.”
  • Everything is a Table: Lua’s sole composite data structure is the table, which acts as list, dictionary, object, and more. Technically, it’s powerful and flexible—tables can have numeric indices for arrays, string keys for maps, and even metatables for prototype-based objects. But during a quick showcase, telling someone “oh yeah, we don’t exactly have classes or arrays, you just use tables for everything” can sound like you’re making excuses for a lack of features. It’s as if your favorite Swiss Army knife of a language chooses to call every tool in it a “table” just because it can shape-shift. A senior developer in the audience might raise an eyebrow and say “So... no dedicated array or object type? Just one type to rule them all?” – a mixture of skepticism and amusement.

The Languages category context here highlights how different programming communities have their own norms and the culture shock when those norms collide. Historically, Lua’s one-based indexing harks back to older languages (like FORTRAN or MATLAB) and mathematics contexts where counting from 1 is natural. Meanwhile, most modern languages influenced by C use 0-based indexing (because of how array addresses calculate offset from a base pointer — base + index * element_size, making index 0 elegantly point to the base). Thus, introducing Lua in a crowd of C/Python/JavaScript developers can feel like introducing a friend who greets everyone with an inside joke nobody else gets. The meme captures that awkwardness perfectly. The blue character’s pride turning into embarrassment is something any tech presenter fears: the moment when a beloved framework’s DeveloperHumor worthy quirks surface, and you have to pause your polished demo to explain “It’s not a bug, it’s a feature, I swear!”

In essence, Level 3 analysis recognizes the meme as a lighthearted jab at how DeveloperExperience can be affected by these fundamental design decisions. The joke lands because it’s RelatableDeveloperExperience: every experienced dev has had a “favorite tool demo” disrupted by unexpected complexity or an audience’s skepticism of a weird feature. Lua just happens to be the example here, with its drunk little quirks stumbling into the limelight and leaving the language advocate sweating. The meme humorously warns us: before you loudly proclaim a technology as the best thing ever, be ready for its peculiarities to crash the party! It’s a senior-level wink to the wise—know your tools, warts and all, because those warts might just steal the show.

Description

A four-panel comic strip humorously depicting the experience of learning the Lua scripting language. In the first panel, a character with a blue outline enthusiastically points to a building with a 'Lua' sign and logo, telling a plain white character, 'THIS IS MY FAVORITE Scripting Language'. Through a small door in the building, a smaller, red-outlined character is seen drinking from a bottle. The second panel is a silent close-up of the plain character looking skeptical and the blue character starting to sweat. In the final panel, the red character, now outside and holding the bottle, belligerently explains Lua's core concepts in a jagged speech bubble: 'Objects? Everything is a Table, Arrays start at 1,'. The blue character looks on with a strained, sweaty expression of regret. The technical humor stems from Lua's unconventional design choices that defy programming norms, specifically its 1-based array indexing (most languages are 0-based) and its reliance on a single 'table' data structure for everything, which can be jarring for developers accustomed to distinct objects, arrays, and dictionaries

Comments

37
Anonymous ★ Top Pick Lua is the reason senior game devs have trust issues. After years of fighting off-by-one errors, you're suddenly told the real mistake was starting at zero all along
  1. Anonymous ★ Top Pick

    Lua is the reason senior game devs have trust issues. After years of fighting off-by-one errors, you're suddenly told the real mistake was starting at zero all along

  2. Anonymous

    Lua: the only place where shifting every array by +1 is considered both an object model and a design philosophy

  3. Anonymous

    After 20 years of explaining why our Redis Lua scripts have off-by-one errors in production, I've concluded that Lua's 1-based indexing isn't a design choice - it's a distributed systems resilience test disguised as a scripting language feature

  4. Anonymous

    Lua developers will passionately defend 1-based indexing as 'more intuitive for non-programmers' while simultaneously explaining why implementing OOP requires understanding metatables, the __index metamethod, and why `setmetatable({}, {__index = ParentClass})` is 'simple.' It's the language equivalent of saying 'we simplified everything' and then handing you a table that's simultaneously an array, object, hashmap, namespace, and occasionally your entire module system

  5. Anonymous

    Lua: Where tables impersonate objects flawlessly, but that 1-based array has you subtracting instinctively at every embed

  6. Anonymous

    Lua: where OO is sugar on hash maps and off-by-one is a spec, not a bug

  7. Anonymous

    Embedding Lua is great - until your C++ indices meet its 1-based tables and your ‘object system’ is a metatable and a prayer

  8. @SlavaAndreevich 1y

    well, yes, that's why

  9. @Johnny_bit 1y

    "everything is a table" i can accept, but "arrays start at 1"? What fresh hell is this? TurboPascal?

    1. @ashit_axar 1y

      Maybe index 0 is used for storing array length. That way walking the array to find the length is not needed. Just a guess.

      1. @Johnny_bit 1y

        That's exactly what TurboPascal had, especially in terms of strings :) first byte was string length :)

      2. @ZgGPuo8dZef58K6hxxGVj3Z2 1y

        This wouldn't have any use. Many managed languages store raw structs or arrays this way but they will account for it

    2. @Nekitosss8 1y

      Arrays starting at 0 comes from languages like C where position in the array is the memory offset. Offset 0 makes the most sense for those languages. Now most languages don't store arrays/lists in contiguous addresses, so there's no offset used there. For those languages, starting with 1 makes the most sense. Think about it - if you need the first element, you need to type 0. If you need nth element, you always have to count n-1 in your head. The length is always position of the last element +1. If you have array of 6 elements, with 0-based indexing you have to position of the last element = length -1 So, I'd actually prefer 1-based indexing, it is just less complexity that is now mostly not needed

      1. @SamsonovAnton 1y

        We are doomed then. Do those languages reinvent virtual memory management on software level?! 🥴 As for "offset" thing, the reasoning is simple: lower-level languages that sit near hardware as much as possible, use offsets, while higher-level languages for educational and casual user audience tend to use natural numbers as indices. There is also a corner case with math, where storing polynomial coefficients will naturally benefit from starting at zero, but as well as from ability to have negative indices (some languages support that).

        1. @Nekitosss8 1y

          Well, what I meant that it is not guaranteed that the values will be stored in contiguous blocks of memory - I'm talking about higher-level languages where an array is dynamic and its size can be changed at runtime. For lower-level languages 0-based indexes make sense, of course.

          1. Sure Not 1y

            Dutch count floors in a building differently too.

          2. @NaNmber 1y

            so you selected the whole message instead of replying 😌

          3. @SamsonovAnton 1y

            You probably mean associative arrays (dictionaries) and all other kinds of that. Regular arrays may also be dynamic, if the language supports it in one form or another, such as: Dim a(1 To 23) As Integer ReDim Preserve a(1 To 42) or int *a = malloc(23 * sizeof(int)); a = realloc(a, 42 * sizeof(int)); or std::list<int> a(23); a.resize(42); but all those are simple contiguous blocks of memory, reallocated on resize.

            1. @Nekitosss8 1y

              I see. I think it depends on the language, I've heard python's lists are basically linked lists behind the scenes, so I assume the values can be stored all over the place in memory Also, for me arrays==lists (in concept, not in implementation) - an ordered collection of values :) I live a simple life😅

      2. @anilakar 1y

        Sorry, but arrays starting at 1 makes no sense whatsoever. Most of the time you do not need indices at all but just want to loop over the elements. When you actually need indices, you'll just end up having to subtract 1 first, then do the math and finally add back 1 again. *Mic drop*

        1. @Nekitosss8 1y

          If you want to access the last value, you have to do my_list[my_list.length -1] all the time though (if it is not python, where you can just my_list[-1] If you use 0-based indexes then you have to do +/- 1

          1. @anilakar 1y

            How many elements exist between 0 and 5? How many elements exist between -3 and 2, and at which indices?

        2. @SamsonovAnton 1y

          We didn't have for each loops back then — only for and while. (PS. Lisp doest not counr.) When you actually need indices, you'll just end up having to subtract 1 first, then do the math and finally add back 1 again. *Mic drop* This is exactly what Visual Basic .NET is doing: it does not allow having arrays starting from anything but zero, but still uses classic syntax of dimensioning with lower and upper bounding indices: Dim a(0 to n - 1) only to be translated to the intermediate code that subracts and imnediately adds 1 to get the number of elements for allocation: pop sub 1 add 1 dim "Complier will optimize!"?! Ha-ha!

    3. @JackOhSheetImSorry 1y

      Looks like lua is programmable excel sheet, they both start at 1

  10. @callofvoid0 1y

    Are lua Tables more like python dictionaries or c structs?

    1. @kvassilisk 1y

      Actually nowadays they are a bit of both I think it uses an array part only when there are contiguous indices 1..x And a map otherwise?

      1. Sure Not 1y

        _G

  11. @theu_u 1y

    Fun fact: lua(jit) is used for a business logic impl of highload-oriented services, like haproxy runtime, Tarantool DB runtime.. (surely its gc becomes a mess at some point, but.. I love the)

  12. @deadgnom32 1y

    well, that's just a map

    1. @Sun_Serega 1y

      yeah, exactly, because lua arrays are also tables

  13. @Aqualon 1y

    I love lua, apart from having arrays start with 1 it's a great language

  14. @Bjastkuliar 1y

    Most wikis run it😂🙈

  15. @zexUlt 1y

    AFAIK in Lua arrays can start at any index you want. Not just 0 or 1

  16. @anilakar 1y

    Which language are you talking about? Lua tables definitely do not have a .length member. It's #my_list.

    1. @Nekitosss8 1y

      .length is in js, but it doesn't matter what language it is, the concept is the same

  17. @samorosnie 1y

    writing lua scripts for redis felt like writing xslt v1.0

    1. Sure Not 1y

      OpenResty is fun too

Use J and K for navigation