Lua: розьніца паміж вэрсіямі
Змесціва выдалена Змесціва дададзена
Няма апісаньня зьменаў |
Няма апісаньня зьменаў |
||
Радок 7:
Lua быў створаны ў 1993 годзе Раберта Ерусалімскім, Луісам Гэнрыке дэ Фігуэйрэда і Вальдэмарам Салесам, членамі Tecgraf (Computer Graphics Technology Group - групы тэхналогій камп'ютэрнай графікі) у Папскім каталіцкім універсітэце Рыа-дэ-Жанэйра ў Бразіліі .
З 1977 па 1992 год у Бразілія праводзіла палітыку жорсткіх [[Гандлёвы бар'ер|гандлёвых бар'ераў]] (так званых рынкавых рэзерваў) у дачыненьні да
Папярэднікамі Lua былі мовы ''SOL'' (Simple Object Language - простая аб'ектная мова) і ''DEL'' (Data-Entry Language - мова ўвода даных). Яны былі незалежна распрацаваны ў Tecgraf у 1992–1993 гадах, каб дадаць некаторую гнуткасць у два розныя праекты (абодва былі інтэрактыўнымі графічнымі праграмамі для кампаніі Petrobras ). У SOL і DEL не хапала структур кіравання патокам, і Petrobras адчувала ўсё большую патрэбу ў тым, каб дадаць да іх поўную магутнасць праграмавання.
Lua 1.0 быў распрацаваны такім чынам, што яго канструктары аб'ектаў, якія ў той час крыху адрозніваліся ад цяперашняга лёгкага і гнуткага стылю, уключалі сінтаксіс апісання дадзеных SOL (адсюль назва Lua: ''Sol'' азначае «Сонца» на партугальскай мове, а ''Lua'' азначае «Месяц»). [[Сынтаксіс (мова праграмаваньня)|Сынтаксіс]] Lua для структур кіравання ў асноўным быў запазычаны з [[Modula]] ( <code>if</code>, <code>while</code>, <code>repeat</code> / <code>until</code> ), але таксама паспытаў уплыў [[CLU]] (множныя прызначэнні і множныя вяртанні з функцый, як больш простая альтэрнатыва
З цягам часу семантыка Lua падвяргалася ўсё большаму ўплыву Scheme , асабліва з увядзеннем ананімных функцый і поўнага лексічнага ахопу . У новых версіях Lua было дададзена некалькі функцый.
Радок 17:
Версіі Lua да версіі 5.0 выпускаліся пад ліцэнзіяй, падобнай да ліцэнзіі BSD . Пачынаючы з версіі 5.0 і далей, Lua распаўсюджваецца па ліцэнзіі MIT . Абедзве з'яўляюцца дазвольнымі ліцэнзіямі на бясплатнае праграмнае забеспячэнне і амаль аднолькавыя.
== Асаблівасьці ==
Lua звычайна апісваюць як "[[Шматпарадыгмавая
Увогуле, Lua імкнецца прадастаўляць простыя, гнуткія [[Мэтад (праграмаваньне)|мета-функцыі]], якія можна пашыраць па меры неабходнасці, а не набор функцый, характэрны для адной парадыгмы праграмавання. У выніку базавая мова выкарыстоўвае невялікі аб'ём памяці; скампіляваны [[інтэрпрэтатар]] займае толькі каля 247 [[Кілябайт|kB]] .
Як мова з [[Дынамічная тыпізацыя|дынамічнай тыпізацыяй]], прызначаная для выкарыстання ў якасці [[Скрыптовая мова|мовы сцэнарыяў]], Lua досыць кампактная, каб змясціцца на розных хост-платформах. Яна падтрымлівае толькі невялікую колькасць
Lua рэалізуе невялікі набор пашыраных функцый, такіх як
===
<syntaxhighlight lang="lua">
print("Hello, World!")
</syntaxhighlight>
<syntaxhighlight lang="lua">
print "Hello, World!"
</syntaxhighlight>
[[Каментарый (машыннае праграмаваньне)|Каментарый]] у Lua пачынаецца з падвойнага злучка і працягваецца да канца радка, падобна да [[Ada]], [[Eiffel]], [[Haskell]], [[Slovnaft|SQL]] і [[VHDL]]. Шматрадковыя радкі і каментарыі абмежаваныя падвойнымі квадратнымі дужкамі.
<syntaxhighlight lang="lua">
-- аднарадковы каментарый
--[[
шматрадковы
каментарый
]]
</syntaxhighlight>
У наступным прыкладзе рэалізавана функцыя вылічэньня [[Фактарыял|фактарыялу]]:
<syntaxhighlight lang="lua">
function factorial(n)
x = x * i
end
</syntaxhighlight>
=== Кіраванне патокам ===
Lua мае адзіную канструкцыю [[Галінаваньне (машыннае праграмаваньне)|галінаваньня]]: <code>if then end</code> з неабавязковым <code>else</code> і <code>elseif then</code>.
Стандартны аператар <code>if then end</code> патрабуе ўсіх трох ключавых слоў:
<syntaxhighlight lang="lua">
if умова then
-- сцьвярджэньня
end
</syntaxhighlight>
Ключавое слова <code>else</code> можа быць дададзена з суправаджальным блокам аператараў для кіравання выкананнем, калі ўмова <code>if</code> вылічваецца як <code>false</code>:
<syntaxhighlight lang="lua">
if умова then
-- сцьвярджэньня
else
-- сцьвярджэньня
end
</syntaxhighlight>
Множны выбар рэалізуецца канструкцыяй <code>elseif then</code> <syntaxhighlight lang="lua"> if
-- сцьвярджэньне
elseif
-- сцьвярджэньне
else
-- сцьвярджэньне
end
</syntaxhighlight>
Lua мае чатыры тыпы ўмоўных [[Цыкал (машыннае праграмаваньне)|цыклаў]]: <code>while</code>, <code>repeat</code> (падобны на <code>do while</code>), лікавы <code>for</code> і агульны <code>for</code>.
<syntaxhighlight lang="lua">
while
-- сцьвярджэньне
end
repeat
-- сцьвярджэньне
until
for i = first, last, delta do -- delta
-- сцьвярджэньне
end
</syntaxhighlight>
Гэты <code>for</code> будзе перабіраць табліцу <code>_G</code> з выкарыстаннем стандартнай функцыі ітэратараў <code>pairs</code> пакуль не верне <code>nil</code>:
<syntaxhighlight lang="lua">
for key, value in pairs(_G) do
end
</syntaxhighlight>
Цыклы таксама могуць быць укладзенымі (змяшчацца ўнутры іншага цыкла).
<syntaxhighlight lang="lua">
local grid = {
}
for y, row in pairs(grid) do
print(x, y, value)
end
</syntaxhighlight>
=== Функцыі ===
Абыходжанне з функцыяй як сутнасцю [[Першаклясная функцыя|першае клясы]] паказана ў наступным прыкладзе, дзе паводзіны функцыі <code>print</code> зменены:
<syntaxhighlight lang="lua">
do
-- захоўваем функцыю print як oldprint
-- перанакіроўваем выклік print
oldprint(s == "foo" and "bar" or s)
end
</syntaxhighlight>
Любыя будучыя выклікі <code>print</code> цяпер будуць накіроўвацца праз новую функцыю, з-за [[Ляксычны ахоп|ляксычнага ахопу]] Lua старая функцыя <code>print</code> будзе даступная толькі цераз новаю змененую <code>print</code>.
Lua таксама падтрымлівае [[Замыканьне (інфарматыка)|замыканні]], як паказана ніжэй:
<syntaxhighlight lang="lua">
function addto(x)
-- вяртаем новую функцыю, якая дадае x да аргументу
--[[ Калі мы зьвяртаемся да зьменнай x па-за межамі яе ахопу,
Lua робіць замыканьне. ]]
return x + y
end
fourplus = addto(4)
print(fourplus(3)) --
</syntaxhighlight>
Новае замыканне для зменнай <code>x</code> ствараецца кожны раз, калі выклікаецца <code>addto</code>, так што кожная новая вернутая ананімная функцыя будзе заўсёды мець доступ да ўласнага параметру <code>x</code>.
=== Табліцы ===
Табліца - адзіны убудаваны [[складаны тып даных]] у Lua, аснова усіх тыпаў, ствараемых карыстальнікамі. Яна ўяўляе сабой асацыятыўны масіў з наданнем аўтаматычнага лічбавага ключа і спецыяльнага сінтаксісу.
Табліцы ствараюцца з дапамогай сінтаксісу канструктара <code>{}</code>
<syntaxhighlight lang="lua"> a_table = {} -- новая пустая табліца
</syntaxhighlight>
Табліцы заўсёды перадаюцца па спасылцы.
Ключ (індэкс) можа быць любым значэньнем, нават функцыяй, але не <code>nil</code> і не [[NaN]].
<syntaxhighlight lang="lua">
a_table = { x = 10 } -- новая табліца з адным значэньнем 10 па ключу "x"
print(a_table["x"]) -- друкуе значэньне па ключу "x", у гэтым выпадку 10
b_table = a_table
print(b_table["x"]) -- друкуе 20
print(a_table["x"]) -- таксама друкуе 20, таму што a_table і b_table спасылаюцца на тую самую табліцу
</syntaxhighlight>
Табліца часта ўжываецца як структура (або [[Запіс (структура даных)|запіс]]), выкарыстоўваючы [[Радок (тып даных)|радкі]] ў якасці ключоў. Паколькі такое выкарыстанне вельмі распаўсюджана, Lua мае спецыяльны сынтаксіс для доступу да такіх палёў.
<syntaxhighlight lang="lua">
point = { x = 10, y = 20 } -- новая табліца
print(point["x"]) -- друкуе 10
-- Тое самае што і радок вышэй. Кропкавая натацыя карацейшая і больш простая для ўспрыманьня.
print(point.x)
</syntaxhighlight>
Табліца можа падысьці у якасьці прасторы імёнаў, калі захоўваць у ёй функцыі.
<syntaxhighlight lang="lua">
Point = {}
Point.new = function(x, y)
return {x = x, y = y}
end
Point.set_x = function(point, x)
point.x = x
end
</syntaxhighlight>
Элементам табліцы аўтаматычна надаюцца лічбавыя ключы, што дазваляе выкарыстоўваць табліцы як [[Масіў (структура даных)|масівы]]. Першы аўтаматычны індэкс роўны 1, а не 0, як у многіх іншых мовах праграмавання (але яўны індэкс 0 магчымы).
Лічбавы ключ <code>1</code> не тое самае што радковы ключ <code>"1"</code>.
<syntaxhighlight lang="lua">
-- індэксы задаюцца аўтаматычна
array = { "a", "b", "c", "d" }
-- Друкуе "b". Аўтаматычныя індэксы ў Lua пачынаюцца з 1.
print(array[2])
-- Друкуе 4. # - аператар памеру для табліц і радкоў.
print(#array)
-- нуль - дазволены індэкс
array[0] = "z"
-- Усё яшчэ друкуе 4, так як масівы Lua індэксуюцца з 1.
print(#array)
</syntaxhighlight>
Памер табліцы <code>t</code> вызначаецца як любы цэлы індэкс <code>n</code> такі што <code>t[n]</code> не <code>nil</code> і <code>t[n+1]</code> роўны <code>nil</code>; акрамя таго, калі <code>t[1]</code> <code>nil</code>, <code>n</code> можа быць роўным нулю. Для рэгулярнага масіву з ненулявымі значэннямі ад 1 да дадзенага <code>n</code> яго памер дакладна роўны <code>n</code>, індэксу яго апошняга значэння. Калі масіў мае "дзіркі" (нулявыя значэнні паміж іншымі значэннямі, выдатнымі ад нуля), то <code>#t</code> можа быць любым з індэксаў, які непасрэдна папярэднічае <code>nil</code> значэнню (гэта значыць, ён можа разглядаць любое такое нулявое значэнне як канец масіву).
<syntaxhighlight lang="lua">
ExampleTable =
{
Радок 173 ⟶ 280:
{5, 6, 7, 8}
}
print(ExampleTable[
print(ExampleTable[2][4]) -- друкуе "8"
</syntaxhighlight>
Табліца можа быць масівам аб'ектаў.
<syntaxhighlight lang="lua">
-- канструктар Point
function Point(x, y)
-- вяртаецца новы аб'ект
return { x = x, y = y }
end
-- ствараецца масіў кропак
array = { Point(10, 20), Point(30, 40), Point(50, 60) }
-- друкуе 40
print(array[2].y)
</syntaxhighlight>
Выкарыстанне хэш-табліцы для эмуляцыі масіву звычайна павольней, чым выкарыстанне фактычнага масіву; аднак табліцы Lua аптымізаваны для выкарыстання ў якасці масіваў, каб пазбегнуць гэтай праблемы.
=== Мэтатабліцы ===
Пашыраемая сэмантыка з'яўляецца ключавой асаблівасцю Lua, а канцэпцыя мэтатабліцы дазваляе гібкую наладу табліц. У наступным прыкладзе дэманструецца "бясконцая" табліца. Для любога <code>n</code> <code>fibs[n]</code> дасць <code>n</code>-ы [[лік Фібаначы]] з дапамогай [[Дынамічнае праграмаваньне|дынамічнага праграмавання]] і [[Мэмаізацыя|мэмаізацыі]].
<syntaxhighlight lang="lua">
-- пачатковыя значэньні fibs[1] і fibs[2].
fibs = { 1, 1 }
setmetatable(fibs, {
-- __index - спецыяльная функцыя Lua, якая выклікаецца калі табліца не мае пазначанага ключа
__index = function(values, n)
-- вылічаем і запамінаем fibs[n]
values[n] = values[n - 1] + values[n - 2]
return values[n]
end
})
</syntaxhighlight>
=== Аб'ектна-арыентаванае праграмаванне ===
Нягледзячы на тое, што Lua не мае ўбудаванай канцэпцыі [[Кляса (праграмаваньне)|клясаў]], [[Аб’ектна-арыентаванае праграмаваньне|аб'ектна-арыентаванае праграмаванне]] можа эмулявацца з дапамогай функцый і табліц. Аб'ект фармуецца шляхам размяшчэння метадаў і палёў у табліцы. [[Успадкоўваньне (аб'ектна-арыентаванае праграмаваньне)|Успадкоўваньне]] (як адзінкавае, так і множнае) можа быць рэалізавана з дапамогай метатабліц, дэлегуючы неіснуючыя метады і палі бацькоўскаму аб'екту.
У гэтым выпадку такога паняцця як «кляса» не існуе; хутчэй, гэта падобна да [[Прататыпнае праграмаваньне|прататыпнага ўспадкоўваньня]], як у [[Self]] або [[JavaScript]]. Новыя аб'екты ствараюцца альбо [[Фабрычны мэтад|фабрычным мэтадам]] (які стварае новыя аб'екты з нуля), альбо шляхам кланаваньня існуючага аб'екта.
Стварэнне простага аб'екта, які апісвае [[вэктар]]:
<syntaxhighlight lang="lua">
local Vector = {}
local VectorMeta = { __index = Vector }
-- Канструктар клясы Vector
return setmetatable({ x = x, y = y, z = z }, VectorMeta) end
function Vector.magnitude(self)
end
-- стварэньне новага вэктара
local vec = Vector.new(0, 1, 0)
-- выклік мэтада
print(vec.magnitude(vec))
-- доступ да поля x
print(vec.x)
</syntaxhighlight>
Тут <code>setmetatable</code> загадвае Lua шукаць элемент у табліцы <code>Vector</code>, калі ён адсутнічае ў табліцы <code>vec</code>. <code>vec.magnitude</code>, тое самае што і <code>vec["magnitude"]</code>, спачатку шукае элемент <code>magnitude</code> у табліцы <code>vec</code>. Табліца <code>vec</code> не мае элемента <code>magnitude</code>, але яе мэтатабліца дэлегуе элемент <code>magnitude</code> ў табліцу <code>Vector</code>, калі ён не знойдзены ў табліцы <code>vec</code>.
Lua мае некаторы [[сынтаксічны цукар]] для палягчэння апісання клясы. Каб аб'явіць функцыі-члены ўнутры табліцы-прататыпа, можна выкарыстоўваць <code>function table:func(args)</code>, што эквівалентна <code>function table.func(self, args)</code>. Для выкліку мэтадаў клясы таксама можа выкарыстоўваць двукроп'е: <code>object:func(args)</code>, тое самае <code>object.func(object, args)</code>.
Улічваючы гэта, вось адпаведны клас з <code>:</code> сінтаксічным цукрам:
<syntaxhighlight lang="lua">
local Vector = {}
Vector.__index = Vector
-- Канструктар клясы Vector
--[[ Так як мэтад створаны пры дапамозе двукроп'я,
"self" няяўна перадаецца як першы аргумэнт. ]]
end
function Vector:magnitude()
return math.sqrt(self.x^2 + self.y^2 + self.z^2)
end
-- новы вэктар
local vec = Vector:new(0, 1, 0)
-- выклік мэтада
print(vec:magnitude())
-- доступ да поля "x"
print(vec.x)
</syntaxhighlight>
====
Успадкоўваньне у Lua таксама магчыма з дапамогай мэтатабліц. У наступным прыкладзе мы рэалізуем аперацыю памнажэння вектара на канстанту ў вытворным класе.
<syntaxhighlight lang="lua">
local Vector = {}
Vector.__index = Vector
--- канструктар клясы Vector
function Vector:new(x, y, z)
--[[ Here, self refers to whatever class's "new"
-- method we call. In a derived class, self will
-- be the derived class; in the Vector class, self
-- will be Vector ]]
return setmetatable({x = x, y = y, z = z}, self)
end
function Vector:magnitude()
return math.sqrt(self.x^2 + self.y^2 + self.z^2)
end
Радок 276 ⟶ 434:
vec:multiply(2) -- Multiply all components of vector by 2
print(vec.y) -- Access member again (output: 2)
</syntaxhighlight>
Lua таксама падтрымлівае [[Множнае успадкоўваньне|множнае ўспадкоўваньне]]; <code>__index</code> можа быць функцыяй або табліцай. [[Перагрузка аператара]] таксама можа быць зроблена; мэтатабліцы Lua могуць мець такія элементы, як <code>__add</code>, <code>__sub</code> і гэтак далей.
== Рэалізацыя ==
Праграмы на Lua не інтэрпрэтуюцца непасрэдна з тэкставага файла, а кампілююцца ў байт-код, які потым запускаецца на віртуальнай машыне Lua. Працэс кампіляцыі звычайна нябачны для карыстальніка і выконваецца падчас выканання, асабліва калі выкарыстоўваецца JIT-кампілятар, але ён можа быць выкананы загадзя, каб паскорыць загрузку або, прыбраўшы кампілятар, паменшыць аб'ём памяці хост-асяроддзя. Кампіляцыя у байт-код магчыма таксама ўнутры праграмы на Lua, выкарыстоўваючы функцыю <code>dump</code> з бібліятэкі радкоў альбо функцыі <code>load/loadstring/loadfile</code>.
|