More Lua. Expressions Arithmetic operators */-+ “real” numbers only ^ exponentiation a%b == a -...
-
Upload
chloe-marsh -
Category
Documents
-
view
221 -
download
0
Transcript of More Lua. Expressions Arithmetic operators */-+ “real” numbers only ^ exponentiation a%b == a -...
More Lua
Expressions• Arithmetic operators */-+
• “real” numbers only
•^ exponentiation
• a%b == a - floor(a/b)*b
• x%1 gives fractional part, x-x%1 integer part
• angle = (angle + delta) % (2*math.pi)
• keeps angle in [0,2π)
• Relational operators
• < > <= >= == ~=
• return true or false
• if values are different types, they are not equal
• compares as references tables, fucntions, userdata -- must be ref to same object to be equal
• ordering (<,>,<=,>=) defined only for strings and numbers
• other types only compare for equality
• 2<15 ~= “2” < “15”. 2 < “15” gives error
• Logical operators - and, or not
• false and nil are false, anything else is true
• short circuit evaluation
• and returns first argument if false, else second argument.
• or returns first argument if true, else second argument.
• ex) type(v)==”table” and v.tag=value
• ex) x=(x or v) --assigns v to x if x is not intialized
• ex) a and b or c -- same as a?b:c in C/C++
• max = (x>y) and x or y
• ‘and’ has higher precedence than ‘or’
• not always returns true or false
• not 0 == true
• not nil == true
• String Concatenation ..
• print(‘Hello ‘ .. ‘World’)
• Precedence (if in doubt, use parens!)
^
not # - (unary)
* / %
+ -
..
< > <= >= ~= ==
and
or
• Table Constructors
• expressions that create and initialize tables
• ex) species={‘Acamarian’, ‘Andorian’, ‘Denebian’, ‘Antaran’, ‘Klingon’,‘Human’}
• first value has index 1, not 0
• ex) ship={ammo=100, health=100}
• same as: ship={}; ship.ammo=100; ship.health=100
• constructor just initializes and creates a new table (all tables are same type)
• ex) linked list stack!
• create one with lines from a file
list = nil
for line in io.lines() do
list = {next=list, value=line}
• traverse it
local p = list
while p do
print ( p.value )
p = p.next
end
• can mix keyed values and lists in constructor
ex) polyline = {color=‘blue’, thickness=2,
npoints = 4,
{x=0, y = 0},
{x=-10, y=0},
{x=-10, y=1},
{x=0, y=1}
}
• print(polyline[2].x) --> -10
• can’t use constructors for keys that are negative numbers or non-identifier strings. for those ,use this syntax:
• ex) expletives={[“$^%”] = ‘golly’, [“-1”] = ‘oops’, [“#%*”] = ‘shucks’}
• {x=0,y=0} same as {[“x”]=0, [“y”]=0}
• can use ; instead of , as separator
• can have one after the last entry (easier metaprogramming)
Statements• Assignment: changing the value of a variable or
table field
• multiple assignment
• a,b = 10, 2*x
• x,y = y,x -- swaps x and y since rhs evaluated before any assignments
• if rhs list shorter than lhs list, rest get nil
• if lhs list shorter than right, extra values discarded
• functions can return multiple values
• Local variables and Blocks
• lunch = 10 --global variable
• local snack = ‘tribble’ -- local variable
• scope of local = block (body of control structure) or chunk
x = 10local i = 1
while i <= x do local x = i*2 print(x) i = i + 1end
if i > 10 then local x x = 20 print (x+2) -- would print 22 else print (x) -- 10 (global) end
print (x) -- 10 (global)
•can create blocks with do and end
do
local x = r*cos(theta)
local y = r*sin(theta)
dropBomb(posx+x, posy+y)
end
•common idiom: init a local with a global of the same name (faster, can change it without side effects)
local foo = foo
Control Structures• If then else
if age<21 then booze=0 end
if weight > 200 then
exercise()
hungry = 0
end
•elseif useful ( no switch stmt!), only needs one ‘end’
if collar == ‘up’ then
spaz = spaz + 2
elseif collar == ‘buttondown’ then
spaz = spaz + 1
elseif collar == ‘missing’ then
spaz = spaz - 1
elseif collar == ‘lipstick’ then
spaz = spaz - 2
end
•while -- loops until condition is false
a={0,1,2,3,4,5,'hahah', 6, 7}
local i = 1
while a[i] do
print (a[i])
i = i + 1
end
• repeat-until -- post-test loop (1 or more iterations)
• scope of locals includes the condition
-- print first non-empty line
repeat
line = io.read()
until line ~= ''
print (line)
x = 99
local sqr = x/2
repeat
sqr = ( sqr + x/sqr) / 2
local error = math.abs ( sqr^2 - x )
until error < x/ 10000 -- ‘error’ in scope here
print ('x',x)
print ('sqr',sqr)
• for
• numeric for
for var=initval, testval, step do
<something>
end
•step optional (default=1)
•all vals evaluated ONCE at start of loop
•control variable is a local, only visible in body
•never change the value of the control var!
•use break to exit loop early
• Generic for
• executes body once for each value of an iterator function
a={'dog','cat',5, {1,2,3}, shoppinglist='socks',
setdate=function(dt) date=dt end}
for i,v in ipairs(a) do
print (i, v)
end
print ('keys=')
for k in pairs(a) do
print (k)
end
• break and return
• break to exit the innermost loop its within
• return returns a value from a function (or just exits it if no value returned)
• break and return must be the last statement of a block
for i,v in ipairs(a) do print (i, v) if v == 5 then break endend
printKeys = function (t) print ('keys until 5=') for k in pairs(t) do print (k) if ( t[k] == 5 ) then return end endend
printKeys(a)
Functions• ex) print ( ‘a’, a )
• args in parentheses
• exception: if a single argument, and its a literal string or a table constructor, parens not needed
• ex) print “Hello,World”
• ex) f {x=0,y=10}
• special syntax for OOP
• o:foo(x) same as o.foo(o,x)
• function definition
• parameters are local variables
a={'dog','cat',5, {1,2,3}, shoppinglist='socks', setdate=function(dt) date=dt end}
function summation (t) local sum = 0 for k in pairs(t) do print (k) if type(k)=='number' then sum = sum + k end end return sumend
sum = summation(a)print ('sum = ', sum)
• if fewer args than params, extra params get nil
• if more args than params, extra args discarded
•ex) default argument idiom
function incrCount (n)
n = n or 1
count = count + n
end
•can return multiple values, list them after return
• variable number of arguments
function summation (...) local sum = 0 for i,v in ipairs{...} do print (v) if type(v)=='number' then sum = sum + v end end return sumend
sum = summation(1,2,3,4)print ('sum = ', sum)
function argsim ( ... ) local a, b, c = ... print (a,b,c) return a,bend
function foo1 ( ... ) print ('calling foo with args', ... ) foo ( ... )end
• named arguments
• Lua uses positions to match args with params
• to get named args with default values, pass a table to the function, and write the function to extract the named args from the table
function foo (options)
_foo ( options.x or 0,
options.y or 0,
options.width or 1,
options.background or “white”)
end
More About Functions
• Lua functions
• are first-class values - can be stored in variables, tables, passed as args, etc. like any other values
• have “lexical scoping”
• can access variables of their enclosing functions
• are anonymous
• the syntax
• function foo(x) return 2*x end
• is syntactic sugar for
• foo = function(x) return 2*x end
• can pass an anonymous function to another function as a parameter
• ex)
• table.sort(atable, function (a,b) return (a.name > b.name) end)
• a “higher-order function” is a function taking a function as an parameter
• ex)
function derivative ( f, delta )
delta = delta or 1e-4
return function (x)
return(f(x+delta) - f(x))/delta
end
end
c = derivative(math.sin)
print(cos(10), c(10))
Closures• when a function b() is written inside a
function a(), the inner function (b) has access to the variables of the enclosing function (a)
• even after the enclosing function exits!
• the function retains a reference to the variable, so if it was a local (to a()) it will not be deleted as long as b() exists.
• the variable so referenced is called “non-local” or a “Lua upvalue”
• closure example
function newCounter() local i = 0 return function () i = i+1 return i endend
c1 = newCounter()print(c1())print(c1())print(c1())
c2 = newCounter()print(c2())print(c1())print(c2())
•closures are useful for callback functions
function digitButton(digit)
return Button{ label=tostring(digit)
action = function()
add_to_display(digit)
end
}
•can redefine existing function with closures
do
local oldSin = math.sin
localk = math.pi/180
math.sin = function (x) return oldSin(x*k) end
end