לואה (שפת תכנות)

היסטוריה

Lua החלה את דרכה בשנת 1993 בפרויקטים שנכתבו באוניברסיטה הקתולית בריו עבור חברת הנפט הברזילאית פטרוברז. היו צריכים לתאר בקלות נתונים מסוגים מגוונים. התברר להם שהדרך היעילה ביותר לייצג אותם היא על ידי שפת תכנות ייעודית. לפני שכתבו את Lua כתבו גם שפה מוגבלת יותר בשם Sol (ראשי תיבות באנגלית של Simple Object Language, אך גם המילה ”שמש“ בפורטוגזית).

קהילה

למרות יעודה כשפה משובצת (התלויה בעיקר בשפת C), Lua הצליחה לצבור פופולריות ותאוצה בשנים האחרונות בין מפתחי קוד פתוח ולה קהילה עצמאית שמפתחת לה כלים וספריות המאפשרים בה פיתוח נוח ורב תחומי ללא תלות ב־C או בשפות אחרות.

LuaRocks

מערכת ניהול החבילות של Lua (הופיעה לראשונה ב־2007, הכתובה גם היא בשפה עצמה) נקראת LuaRocks והיא מאפשרת שיתוף ספריות וקוד הכתובים ב־Lua. החבילות עצמן מכונות ”rocks“ בצירוף פירוש שם השפה Lua בפורטוגזית ”ירח“, נגזר המונח ”אבני ירח“ לתאר פיסות קוד הכתובות בשפה שהם בדרך כלל רכיבי Lua או אסופות של רכיבים המספקים פונקציונליות ממוקדת מטרה.
המערכת יודעת לטפל ביחסי תלות בין החבילות עצמן, בגרסאות שלהן, ושל מפרש ה־Lua הזמין במחשב ויוצרת סביבה נוחה לפיתוח יציב ושיתופי ב־Lua. החבילות מסודרות במקום מרוכז בכל מחשב וכך חוסכות הכלה מיותרת של אותם רכיבים בכל פרויקט Lua חדש.
מבין המיזמים המוכרים ביותר בקהילה נמנים Kepler Project שהפך את Lua כשפה ייעודית עבור יישומוני רשת, ואת כלי התיעוד והביאור LuaDoc ו־LDoc, שהם כלי התיעוד והביאור העיקריים כיום עבור קוד שכתוב ב־Lua.
נכון ל־2019, הנתונים הסטטיסטים של LuaRocks מראים כ־20 אלף חברים רשומים (אין צורך להיות רשום כדי להוריד חבילות), כ־2500 חבילות זמינות, ובין 40 ל־60 אלף הורדות יומיות.

תוכניות לדוגמה

הדפסת ההודעה "Hello world":
print("Hello world")-- Lua allows to call functions without parenthesis when there's only one parameter:print "Hello world"
הערה בת שורה אחת מתחילה בזוג מקפים. הערה בת שורות אחדות מתחילה בזוג מקפים ואחריהם זוג סוגריים מרובעים, ומסתיימת בזוג סוגריים מרובעים (כך נכתבת הערה גם ב-SQL). Lua מאפשרת גם קינון הערות מרובות שורות בעזרת הכלת התו ‚=’ באופן מאוזן בין הסוגרים המרובעות בכל אגף.
-- A comment in Lua starts with a double-hyphen and runs to the end of the line.--[[ Multi-line strings & comments are adorned with double square brackets.]]--[[ Level 1 fold --[==[ Level 2 fold --[===[ Level 3 fold        --]===]    --]==]  ]]
לולאת for:
-- Plain for loop:for i = 1, 5 do
 -- Statementsend-- Loop through each item in a table. (simlar to "foreach" in other languages)-- Since the keys are strings, the order of iteration is not guaranteed.local days = {
  ["Sunday"] = 1,
  ["Monday"] = 2,
  ["Tuesday"] = 3,
  ["Wednesday"] = 4,
  ["Thursday"] = 5,
  ["Friday"] = 6,
  ["Saturday"] = 7}for key, value in pairs(days) do
 -- 'key' is a string that represents the actual index.
 -- 'value' represents `days[key]`, similarly `days["Monday"]` will return 2.end-- Loop through each item in a table, and count their index.local days = {
 "Sunday",
 "Monday",
 "Tuesday",
 "Wednesday",
 "Thursday",
 "Friday",
 "Saturday"}for index, key in ipairs(days) do
 -- 'index' is a number, that can be used as `days[i]`.
 -- 'key' represents the actual item, ie. "Monday".end
שגרה רקורסיבית לחישוב עצרת בלי ועם האופטימיזציה האופיינית לתכנות ב־Lua:
-- Naive recursion without cache is not recommended in Lua.function factorial(n)
 if n == 0 then
 return 1
 else
 return n * factorial(n - 1)
 endend-- Recursion with a memoized cache table will make the function perform much faster in future calls, thus is strongly encouraged in Lua if the extra memory can be afforded during execution time.local cache = {
  [0] = 0,
  [1] = 1}function factorial(n)
 -- Note that 0 doesn't evaluate to 'false' in Lua.
 if not cache[n] then
 cache[n] = n * factorial(n - 1)
 end
 -- Instant retrieval time for previously computed values.
 return cache[n]end
פונקציות ב־Lua הן משתנים לכל דבר, וניתן להקצות להם שמות משתנים חדשים או להעביר אותן כפרמטרים.
-- Declare a local scope with `do - end` where the redefinition of `print` will be valid.do
 -- Store the current `print` function as oldprint
 local oldprint = print

 -- Redefine the `print` function
 local function print(message)
 if message == "foo" then
 oldprint("bar")
 else
 oldprint(message)
 end
 end

 -- Test the new override:
 print("Hello world") --> Hello world
 print("foo") --> bar
 oldprint("foo") --> fooend-- Once exiting the `do - end` scope, `print` reverts to its original meaning.print("foo") --> foo

מימושים עיקריים

מהיותה שפה זעירה וחופשית שנועדה לשיבוץ, ל־Lua קיימים מימושים רבים שפותחו במשך השנים למגוון מטרות שונות על ידי מפתחים וצוותים עצמאים. בין המימושים קיימים הבדלים ואי־תאימויות לאור המגבלות שמולן הם נעמדו או עקב שינויים ללא תאימות לאחור שחלו במימוש הקנוני של Lua מהאוניברסיטה הקתולית (PUC Rio).
מצב זה העמיד קושי לקהילת החופשית של Lua ולמיזם מערכת ניהול החבילות שלה (LuaRocks) לנסות ליצור שיתוף פעולה ותיאום בין החבילות הזמינות שהציעו מפתחים מול הגרסאות השונות של השפה שחלו במימושים המועדפים עליהם.
בסביבות 2015 הקהילה התפצלה לשני מחנות מרכזיים והם Lua 5.3 ו־Lua 5.1 עקב ההתנגדות הנחרצת שהביע היוצר של LuaJIT מליישם את השינויים החדשים של Lua 5.3 ב־LuaJIT לאחר שכבר הביע התנגדות קודמת לשינויים של Lua 5.2 אף על פי שיישם את חלקם.
נכון ל־2019 רוב החבילות ב־LuaRocks זמינות בגרסאות Lua 5.3 ו־Lua 5.1 בעיקר כדי לשמור על תאימות לאחור עם LuaJIT, שהוא המימוש המועדף על חלק ניכר מהקהילה.

Lua (PUC Rio)

זהו המימוש המרכזי והנפוץ ביותר של Lua ונהוג לעיתים לכנות אותו PUC Lua. הוא מפותח באוניברסיטה הקתולית (PUC Rio) שבריו דה ז'ניירו בברזיל מאז 1993 ומופץ תחת רישיון MIT. PUC Lua הוא מפרש זעיר ודינמי הכתוב בשפת C, ומצטיין בצריכה חסכונית של זיכרון וכוח עיבוד למרות ביצועיו המעולים ביחס לשפות מפורשות אחרות.
PUC Lua ממיר קוד מקור של Lua ל־bytecode הסטנדרטי של השפה תוך כדי שהקוד עובר בדיקות ראשוניות כגון חוקיות תחביר לפני הריצה שלו. ניתן לייצא את ה־bytecode שנוצר לתוך קבצים מתוך הקוד בעזרת הפונקציה ()string.dump או מחוץ לקוד בעזרת הפקודה luac במסוף.

LuaJIT

LuaJIT הוא מימוש המכוון לביצועים גבוהים מאוד עם Lua בעזרת הידור תוך כדי זמן ריצה (Just In Time compilation), מפרש שחלקים ממנו כתובים בשפת סף, וממשק FFI (Foreign Function Interface) חדש לתיווך בין Lua ופונקציות ומבני נתונים הכתובים בשפת C בצורה טבעית מבלי לגרוע בביצועים של המפרש.
בנוסף למהדר, גם המפרש של LuaJIT הוא מהיר בהרבה מהמפרש הסטנדרטי של PUC Lua אפילו אם המהדר אינו מופעל כלל. היוצר מייק פּוֹל פיתח את המפרש של LuaJIT באופן עצמאי בלי לפצל את המפרש הסטנדרטי של PUC Lua.
LuaJIT מעודדת את המתכנת להיעזר בפונקציות וספריות הכתובות בשפת C במקום להיעזר בספריות צד שלישי הכתובת ב־Lua. ממשק ה־FFI של LuaJIT מאפשר גישה ושימוש טבעי עם ספריות, מבני נתונים ופונקציות מספריות בשפת C בלי לגרוע בביצועים שלה וגם מבלי צורך להיעזר ב־Lua C API כפי שדרוש במימוש הסטנדרטי של PUC Lua.
הביצועים של LuaJIT לעיתים קרובות מהירים משל PUC Lua 5.1 עשרות מונים. מה שהפך את המימוש לאטרקטיבי עבור מפתחים שנשענים על ספריות גרפיות, יישומי רשת, טכנולוגיות ענן, וחברות תקשורת גדולות.