Two dashes start a oneline comment.

[[
     Adding two ['s and ]'s makes it a
     multiline comment.
]]


 . Variables and flow control.


num =    All numbers are ubles.
 Don't freak out, bit ubles have  bits 
 storing exact int values; machine precision is
 not a problem  ints that need <  bits.

s = 'walternate'   Immutable strings like Python.
t = "ublequotes are also fine"
u = [[ Double brackets
       start and 
       multiline strings.]]
t = nil   Undefines t; Lua has garbage collection.

 Blocks are denoted with keywords like :
while num <  
  num = num     No  or = type operators.


 If clauses:
 num >  
  ('over ')
else s ~= 'walternate'    ~= is not equals.
   Equality check is == like Python; ok  strs.
  io.write('not over \n')   Defaults to stut.
else
   Variables are global by default.
  thisIsGlobal =    Camel case is common.

   How to make a variable local:
  local line = io.read()   Reads next stdin line.

   String concatenation uses the .. operator:
  ('Winter is coming, ' .. line)


 Undefined variables return nil.
 This is not an error:
foo = anUnknownVariable   Now foo = nil.

aBoolValue = false

 Only nil and false are falsy;  and '' are true!
 not aBoolValue  ('twas false') 

 'or' and 'and' are shortcircuited.
 This is similar to the a?b:c operator in Cjs:
ans = aBoolValue and 'yes' or 'no'  > 'no'

karlSum = 
 i = ,     The range includes both s.
  karlSum = karlSum  i


 Use ", , " as the range to count wn:
fredSum = 
 j = , ,   fredSum = fredSum  j 

 In general, the range is begin, [, step].

 Another loop construct:
repeat
  ('the way of the future')
  num = num  
until num == 



 . Functions.


 fib(n)
   n <   return  
  return fib(n  )  fib(n  )


 Closures and anonymous s are ok:
 adder(x)
   The returned  is created when adder is
   called, and remembers the value of x:
  return  (y) return x  y 

a = adder()
a = adder()
(a())  > 
(a())  > 

 Returns, func calls, and assignments all work
 with lists that may be mismatched in length.
 Unmatched receivers are nil;
 unmatched sers are discarded.

x, y, z = , , , 
 Now x = , y = , z = , and  is thrown away.

 bar(a, b, c)
  (a, b, c)
  return , , , , , 


x, y = bar('zaphod')  > s "zaphod  nil nil"
 Now x = , y = , values .. are discarded.

 Functions are firstclass, may be localglobal.
 These are the same:
 f(x) return x  x 
f =  (x) return x  x 

 And so are these:
local  g(x) return math.sin(x) 
local g; g  =  (x) return math.sin(x) 
 the 'local g' decl makes gselfreferences ok.

 Trig funcs work in radians, by the way.

 Calls with one string param n't need parens:
 'hello'   Works fine.



 . Tables.


 Tables = Lua's only compound data structure;
          they are associative arrays.
 Similar to php arrays or js objects, they are
 hashlookup dicts that can also be used as lists.

 Using tables as dictionaries  maps:

 Dict literals have string keys by default:
t = {key = 'value', key = false}

 String keys can use jslike t notation:
(t.key)   Prints 'value'.
t.newKey = {}   Adds a new keyvalue pair.
t.key = nil    Removes key from the table.

 Literal notation  any (nonnil) value as key:
u = {['@!#'] = 'qbert', [{}] = , [.] = 'tau'}
(u[.])   s "tau"

 Key matching is basically by value  numbers
 and strings, but by identity  tables.
a = u['@!#']   Now a = 'qbert'.
b = u[{}]      We might expect , but it's nil:
 b = nil since the lookup fails. It fails
 because the key we used is not the same object
 as the one used to store the original value. So
 strings & numbers are more portable keys.

 A onetableparam  call needs no parens:
 h(x) (x.key) 
h{key = 'Sonmi~'}   Prints 'Sonmi~'.

 key, val in pairs(u)    Table iteration.
  (key, val)


 _G is a special table of all globals.
(_G['_G'] == _G)   Prints 'true'.

 Using tables as lists  arrays:

 List literals implicitly set up int keys:
v = {'value', 'value', ., 'gigawatts'}
 i = , #v    #v is the size of v  lists.
  (v[i])   Indices start at  !! SO CRAZY!

 A 'list' is not a real type. v is just a table
 with consecutive integer keys, treated as a list.


 . Metatables and metamethods.


 A table can have a metatable that gives the table
 operatoroverloadish behavior. Later we'll see
 how metatables support jsprototypey behavior.

f = {a = , b = }   Represents the fraction ab.
f = {a = , b = }

 This would fail:
 s = f  f

metafraction = {}
 metafraction.__add(f, f)
  sum = {}
  sum.b = f.b  f.b
  sum.a = f.a  f.b  f.a  f.b
  return sum


setmetatable(f, metafraction)
setmetatable(f, metafraction)

s = f  f   call __add(f, f) on f's metatable

 f, f have no key  their metatable, unlike
 prototypes in js, so you must retrieve it as in
 getmetatable(f). The metatable is a normal table
 with keys that Lua knows about, like __add.

 But the next line fails since s has no metatable:
 t = s  s
 Classlike patterns given below would fix this.

 An __index on a metatable overloads t lookups:
defaultFavs = {animal = 'gru', food = 'nuts'}
myFavs = {food = 'pizza'}
setmetatable(myFavs, {__index = defaultFavs})
eatenBy = myFavs.animal   works! thanks, metatable

 Direct table lookups that fail will retry using
 the metatable's __index value, and this recurses.

 An __index value can also be a (tbl, key)
  more customized lookups.

 Values of __index,add, .. are called metamethods.
 Full list. Here a is a table with the metamethod.

 __add(a, b)                      a  b
 __sub(a, b)                      a  b
 __mul(a, b)                      a  b
 __div(a, b)                      a  b
 __mod(a, b)                      a % b
 __pow(a, b)                      a ^ b
 __unm(a)                         a
 __concat(a, b)                   a .. b
 __len(a)                         #a
 __eq(a, b)                       a == b
 __lt(a, b)                       a < b
 __le(a, b)                       a <= b
 __index(a, b)     a.b
 __newindex(a, b, c)              a.b = c
 __call(a, ...)                   a(...)


 . Classlike tables and inheritance.


 Classes aren't built in; there are dferent ways
 to make them using tables and metatables.

 Explanation  this example is below it.

Dog = {}                                    .

 Dog:new()                          .
  newObj = {sound = 'woof'}                 .
  self.__index = self                       .
  return setmetatable(newObj, self)         .


 Dog:makeSound()                    .
  ('I say ' .. self.sound)


mrDog = Dog:new()                           .
mrDog:makeSound()   'I say woof'          .

 . Dog acts like a class; it's really a table.
 .  tablename:fn(...) is the same as
     tablename.fn(self, ...)
    The : just adds a first arg called self.
    Read  &  below  how self gets its value.
 . newObj will be an instance of class Dog.
 . self = the class being instantiated. Often
    self = Dog, but inheritance can change it.
    newObj gets self's s when we set both
    newObj's metatable and self's __index to self.
 . Reminder: setmetatable returns its first arg.
 . The : works as in , but this time we expect
    self to be an instance instead of a class.
 . Same as Dog.new(Dog), so self = Dog in new().
 . Same as mrDog.makeSound(mrDog); self = mrDog.



 Inheritance example:

LoudDog = Dog:new()                            .

 LoudDog:makeSound()
  s = self.sound .. ' '                        .
  (s .. s .. s)


seymour = LoudDog:new()                        .
seymour:makeSound()   'woof woof woof'       .

 . LoudDog gets Dog's methods and variables.
 . self has a 'sound' key from new(), see .
 . Same as LoudDog.new(LoudDog), and converted to
    Dog.new(LoudDog) as LoudDog has no 'new' key,
    but es have __index = Dog on its metatable.
    Result: seymour's metatable is LoudDog, and
    LoudDog.__index = LoudDog. So seymour.key will
    = seymour.key, LoudDog.key, Dog.key, whichever
    table is the first with the given key.
 . The 'makeSound' key is found in LoudDog; this
    is the same as LoudDog.makeSound(seymour).

 If needed, a subclass's new() is like the base's:
 LoudDog:new()
  newObj = {}
   set up newObj
  self.__index = self
  return setmetatable(newObj, self)



 . Modules.



[[ I'm commenting out this section so the rest of
   this script remains runnable.
 Suppose the file mod.lua looks like this:
local M = {}

local  sayMyName()
  ('Hrunkner')


 M.sayHello()
  ('Why hello there')
  sayMyName()


return M

 Another file can use mod.lua's ality:
local mod = ('mod')   Run the file mod.lua.

  is the standard way to include modules.
  acts like:     ( not cached; see below)
local mod = ( ()
  
)()
 It's like mod.lua is a  body, so that
 locals inside mod.lua are invisible outside it.

 This works because mod here = M in mod.lua:
mod.sayHello()   Says hello to Hrunkner.

 This is wrong; sayMyName only exists in mod.lua:
mod.sayMyName()   error

 's return values are cached so a file is
 run at most once, even when 'd many times.

 Suppose mod.lua contains "('Hi!')".
local a = ('mod')   Prints Hi!
local b = ('mod')   Doesn't ; a=b.

 file is like  without caching:
file('mod.lua')  > Hi!
file('mod.lua')  > Hi! (runs it again)

 loadfile loads a lua file but esn't run it yet.
f = loadfile('mod.lua')   Call f() to run it.

 loadstring is loadfile  strings.
g = loadstring('()')   Returns a .
g()   Prints out ; nothing ed bee now.

]]