Difference between revisions of "Lua"

From MiniScript Wiki
Jump to navigation Jump to search
 
(5 intermediate revisions by the same user not shown)
Line 107: Line 107:
 
* MiniScript lists are 0-based, rather than 1-based
 
* MiniScript lists are 0-based, rather than 1-based
 
* MiniScript lists are manipulated by [[Slice|slicing]] or [[Dot syntax|dot-syntax]] methods like <c>len</c>, <c>insert</c>, and <c>remove</c>, rather than by functions in the <c>table</c> module.
 
* MiniScript lists are manipulated by [[Slice|slicing]] or [[Dot syntax|dot-syntax]] methods like <c>len</c>, <c>insert</c>, and <c>remove</c>, rather than by functions in the <c>table</c> module.
 +
* MiniScript lists can safely contain [[null]].
 +
* MiniScript lists can be concatenated with the `+` operator.
  
 
=== Maps ===
 
=== Maps ===
  
 
Lua tables (when used as associative arrays, not list-style arrays) are similar in purpose to MiniScript maps, but there are a number of differences.
 
Lua tables (when used as associative arrays, not list-style arrays) are similar in purpose to MiniScript maps, but there are a number of differences.
 +
 +
Maps in MiniScript can take any data type as keys.  In map literals these keys use the same syntax as in any other context (unlike in Lua, where string keys are specified without quotes if they are valid identifiers, or with square brackets plus quotes otherwise).  Instead of <c>=</c>, MiniScript uses <c>:</c> to separate the keys from the values.
 +
 +
{| class="wikitable"
 +
|-
 +
! Lua
 +
! MiniScript
 +
|-
 +
| <pre>d = {one=1, two=2, three=3, ["forty two"]=42}</pre>
 +
| <ms>d = {"one":1, "two":2, "three":3, "forty two":42}</ms>
 +
|}
 +
 +
Accessing items by key is done with square-brackets in both languages.  When the keys are valid identifiers, MiniScript also allows [[dot syntax]].
 +
<ms>print d["one"]
 +
d["one"] = "uno"
 +
d.two = "dos"</ms>
 +
 +
Iterating over the key-value pairs is common in both languages, but the syntax is different.  In MiniScript, iterating over a map gives you, on each iteration, a little map containing <c>key</c> and <c>value</c>.
 +
 +
{| class="wikitable"
 +
|-
 +
! Lua
 +
! MiniScript
 +
|-
 +
| <pre>for k,v in pairs(d)
 +
  do print(k,v)
 +
end</pre>
 +
| <ms>for kv in d
 +
  print kv.key + " " + kv.value
 +
end for</ms>
 +
|}
 +
 +
Commonly used map methods include [[len]], [[remove]], [[hasIndex]], [[indexOf]], [[indexes]], and [[values]].  Note that [[len]] returns the number of key-value pairs in the map, which is different from both <c>getn</c> and <c>#</c> in Lua.
 +
 +
<ms>print "This map has " + d.len + " pairs in it."
 +
print "The keys are: " + d.indexes
 +
print "and values are: " + d.values
 +
if d.hasIndex("two") then
 +
  print """two"" is one of the indexes, and its value is " + d["two"]
 +
else
 +
  print "but ""two"" is not one of the indexes."
 +
end if
 +
print "The index that maps to ""uno"" is: " + d.indexOf("uno")</ms>
 +
 +
Maps can be combined with the `+` operator.
 +
 +
=== Strings ===
 +
 +
Strings in MiniScript and Lua are similar in most ways, though in MiniScript, all strings are composed of Unicode characters and indexing is always by character rather than by byte.  The table below shows common operations in both languages.
 +
 +
{| class="wikitable"
 +
|-
 +
! Task
 +
! Lua
 +
! MiniScript
 +
|-
 +
| Assign a string literal
 +
| s = "Hello world!"
 +
| s = "Hello world!"
 +
|-
 +
| Print the first character of a string<br />
 +
| print(string.sub(s,1,1))
 +
| print s[0]
 +
|-
 +
| Print all but the first 2 characters
 +
| print(string.sub(s,3)
 +
| print s[2:]
 +
|-
 +
| Get the length of a string
 +
| print(#s)
 +
| print s.len
 +
|-
 +
| Combine two strings
 +
| s = "Really... " .. s
 +
| s = "Really... " + s
 +
|-
 +
| Get index of a substring
 +
| idx = string.find(s, "world")
 +
| idx = s.indexOf("world")
 +
|-
 +
| Get substring from ''i'' to ''j''
 +
| print(string.sub(i,j))
 +
| print s[i:j]
 +
|}

Latest revision as of 00:07, 11 December 2022

Lua is a scripting language first released in 1993, and particularly popular as an embedded language. This article compares Lua to MiniScript, and may be useful to people coming to MiniScript with a background in Lua.

For a side-by-side comparison on a collection of short programs, see here.

Similarities

Block Syntax

Both Lua and MiniScript delineate code blocks and control structures with explicit keywords. There are some minor differences in syntax, summarized in the table below.

Lua MiniScript
function / end function / end function
if / elseif / end if / else if / end if
while ... do / end while / end while
for i = 1, 10, 2 do / end
for i in range(1, 10, 2) / end for
repeat / until (no direct equivalent)

The most notable difference is that while Lua uses end alone to terminate a function, if, while, or for block, MiniScript uses end function, end if, end while, and end for respectively. MiniScript lacks a repeat-until structure; the standard idiom is to use a while true (infinite) loop, and break out of it when termination conditions are met.

Data Types

Five of the seven basic types in Lua -- nil, number, string, function, and table -- have direct equivalents in MiniScript. nil is called null in MiniScript, and tables are called maps.

Strings in both languages are immutable. MiniScript strings are Unicode, and index by Unicode character; interpretation of Lua strings is implementation-dependent, and index by byte. While Lua has several ways of writing string literals, in MiniScript, string literals are always enclosed in double-quotes (and if you need a double-quote inside a string literal, write it twice, as in SQL).

greeting = "Hello, ""Bob""!  Pleased to meet you."
print greeting   // prints: Hello, "Bob"!  Pleased to meet you.

While MiniScript maps are conceptually quite similar to Lua tables, their syntax and usage is rather different; see the section on Maps under Differences.

Differences

Variable Scope

In Lua, variables are always global by default; you use the local keyword to explicitly declare a local variable. In MiniScript, variables are always local by default (and are never declared; they spring into being when you assign to them). To update a global variable in MiniScript from within a function, you would use the globals or outer prefix.

Lists

Perhaps the biggest difference between Lua and Python is in handling of array-like data. MiniScript has a list data type with no direct Lua equivalent. Readers comfortable with Python should think of it as a Python-style list; others may find the following table helpful.

Task Lua MiniScript
Create an array literal a = {"one", "two", "three"}
a = ["zero", "one", "two"]
Print the first item in an array
print(a[1]) print a[0]
Print the entire array print(table.concat(a, ", ")) print a
Get the length of an array print(#a) print a.len
Append an item to an array table.insert(a, "foo")
a.push "foo"
Insert item at front of array table.insert(a, 1, "hey") a.insert 0, "hey"
Pop the last item off the array last = table.remove(a) last = a.pop
Pull the first item off the array first = table.remove(a, 1)
first = a.pull
Remove item at index i table.remove(a, i)
a.remove i
Get index of an array item no standard method idx = a.indexOf("two")
Get sub-array from i to j no standard method print a[i:j]

The key differences to note:

  • MiniScript lists are 0-based, rather than 1-based
  • MiniScript lists are manipulated by slicing or dot-syntax methods like len, insert, and remove, rather than by functions in the table module.
  • MiniScript lists can safely contain null.
  • MiniScript lists can be concatenated with the `+` operator.

Maps

Lua tables (when used as associative arrays, not list-style arrays) are similar in purpose to MiniScript maps, but there are a number of differences.

Maps in MiniScript can take any data type as keys. In map literals these keys use the same syntax as in any other context (unlike in Lua, where string keys are specified without quotes if they are valid identifiers, or with square brackets plus quotes otherwise). Instead of =, MiniScript uses : to separate the keys from the values.

Lua MiniScript
d = {one=1, two=2, three=3, ["forty two"]=42}
d = {"one":1, "two":2, "three":3, "forty two":42}

Accessing items by key is done with square-brackets in both languages. When the keys are valid identifiers, MiniScript also allows dot syntax.

print d["one"]
d["one"] = "uno"
d.two = "dos"

Iterating over the key-value pairs is common in both languages, but the syntax is different. In MiniScript, iterating over a map gives you, on each iteration, a little map containing key and value.

Lua MiniScript
for k,v in pairs(d)
   do print(k,v)
end
for kv in d
   print kv.key + " " + kv.value
end for

Commonly used map methods include len, remove, hasIndex, indexOf, indexes, and values. Note that len returns the number of key-value pairs in the map, which is different from both getn and # in Lua.

print "This map has " + d.len + " pairs in it."
print "The keys are: " + d.indexes
print "and values are: " + d.values
if d.hasIndex("two") then
   print """two"" is one of the indexes, and its value is " + d["two"]
else
   print "but ""two"" is not one of the indexes."
end if
print "The index that maps to ""uno"" is: " + d.indexOf("uno")

Maps can be combined with the `+` operator.

Strings

Strings in MiniScript and Lua are similar in most ways, though in MiniScript, all strings are composed of Unicode characters and indexing is always by character rather than by byte. The table below shows common operations in both languages.

Task Lua MiniScript
Assign a string literal s = "Hello world!" s = "Hello world!"
Print the first character of a string
print(string.sub(s,1,1)) print s[0]
Print all but the first 2 characters print(string.sub(s,3) print s[2:]
Get the length of a string print(#s) print s.len
Combine two strings s = "Really... " .. s s = "Really... " + s
Get index of a substring idx = string.find(s, "world") idx = s.indexOf("world")
Get substring from i to j print(string.sub(i,j)) print s[i:j]