if the function call has no arguments, we still must write an empty list () to denote the call.
There is a special case to this rule: if the function has one single argument and that argument is either a literal string or a table constructor(Note,constructor,not a table variable), then the parentheses are optional:
dofile 'a.lua' <--> dofile ('a.lua')
print [[a multi-line <--> print([[a multi-line
message]] message]])
f{x=10, y=20} <--> f({x=10, y=20}),注意,如果a={x=10,y=20}, f a,这样是不行的,一定要 {} 也就是显式注明是table
type{} <--> type({})
Lua also offers a special syntax for object-oriented calls, the colon operator.
An expression like o:foo(x) is just another way to write o.foo(o,x), that is, to
call o.foo adding o as a first extra argument.
Conventional syntax:
-- add the elements of sequence 'a'
function add (a)
local sum = 0
for i = 1, #a do
sum = sum + a[i]
end
return sum
end
Parameters work exactly as local variables, initialized with the values of the
arguments passed in the function call.
You can call a function with a number of arguments different from its number of parameters. Lua adjusts the number of arguments to the number of parameters
extra arguments are thrown away;
extra parameters get nil.
For instance,
function f (a, b) print(a, b) end
It has the following behavior:
f(3) --> 3 nil
f(3, 4) --> 3 4
f(3, 4, 5) --> 3 4 (5 is discarded)
5.1 Multiple Results
s, e = string.find("hello Lua users", "Lua") --return multiple result
print(s, e) --> 7 9
(Note that the first character of a string has index 1.)
example:
function maximum (a)
local mi = 1 -- index of the maximum value
local m = a[mi] -- maximum value
for i = 1, #a do
if a[i] > m then
mi = i; m = a[i]
end
end
return m, mi -- , 隔开
end
print(maximum({8,10,23,12,5})) --> 23 3
========I write :
function findMaxOfTable (tb)
local maxIndex=1;
local maxVal=tb[maxIndex];
for i=1,#tb do
if maxVal<tb[i] then
maxIndex,maxVal=i,tb[i]; --use multiple assigment
end;
end;
return maxIndex,maxVal;
end;
print(findMaxOfTable {2,3,5,1});
function findMaxOfTable2 (tb)
local maxIndex=1;
local maxVal=tb[maxIndex];
for i=1,#tb do
maxIndex=maxVal<tb[i] and i or maxIndex;
maxVal=maxVal<tb[i] and tb[i] or maxVal;
end;
return maxIndex,maxVal;
end;
print(findMaxOfTable2 {2,3,5,1});
When we call a function as a statement, Lua discards all results from the function.
When we use a call as an expression, Lua keeps only the first result.
We get all results only when the call is the last (or the only) expression in a list of expressions.
These lists appear in four constructions in Lua: multiple assignments, arguments to function calls, table constructors, and return statements. 也就是可能出现多值的地方拉,记都不用记
function foo0 () end -- returns no results
function foo1 () return "a" end -- returns 1 result
function foo2 () return "a", "b" end -- returns 2 results
In a multiple assignment, a function call as the last (or only) expression produces as many results as needed to match the variables:
x,y = foo2() -- x="a", y="b" (last expression or only expression)
x = foo2() -- x="a", "b" is discarded (last expression)
x,y,z = 10,foo2() -- x=10, y="a", z="b" (last expression);
x,y = foo0() -- x=nil, y=nil
x,y = foo1() -- x="a", y=nil
x,y,z = foo2() -- x="a", y="b", z=nil
x,y = foo2(), 20 -- x="a", y=20 (Not the last expression,only keep one result)
x,y = foo0(), 20, 30 -- x=nil, y=20, 30 is discarded (NOt the last expression,only keep one result)
print(foo0()) -->
print(foo1()) --> a
print(foo2()) --> a b
print(foo2(), 1) --> a 1 (Not the last expression,only keep one result)
print(foo2() .. "x") --> ax (inside an expression, Lua adjusts the number of results to one;)
t = {foo0()} -- t = {} (an empty table)
t = {foo1()} -- t = {"a"}
t = {foo2()} -- t = {"a", "b"}
t = {foo0(), foo2(), 4} -- t[1] = nil, t[2] = "a", t[3] = 4
Finally, a statement like return f() returns all values returned by f:
function foo (i)
if i == 0 then return foo0()
elseif i == 1 then return foo1()
elseif i == 2 then return foo2()
end
end
print(foo(1)) --> a
print(foo(2)) --> a b
print(foo(0)) -- (no results)
print(foo(3)) -- (no results)
You can force a call to return exactly one result by enclosing it in an extra pair of parentheses:
print((foo0())) --> nil
print((foo1())) --> a
print((foo2())) --> a
a statement like return(f(x)) always returns one single value, no matter how
many values f returns.
A special function with multiple returns is table.unpack. It receives an array
and returns as results all elements from the array, starting from index 1:
print(table.unpack{10,20,30}) --> 10 20 30
a,b = table.unpack{10,20,30} -- a=10, b=20, 30 is discarded,是的可以通过这种方式赋值,but how about
a,b=10,20,30 --函数都不用调用,下面才是这个函数的真正用法,打包参数传递给任意函数
An important use for unpack is in a generic call mechanism.A generic call
mechanism allows you to call any function, with any arguments, In Lua,
if you want to call a variable function f with variable arguments in an array a,
you simply write this:
f(table.unpack(a))
The call to unpack returns all values in a, which become the arguments to f. For
instance, consider the following call:
print(string.find("hello", "ll"))
You can dynamically build an equivalent call with the following code:
f = string.find --f 相当于C 中的函数指针,但在C里面我们也不可以往函数指针里面传递不同的参数,but Lua can
a = {"hello", "ll"}
print(f(table.unpack(a))) --也就是table.unpack 是把参数打包,然后传递给任意函数,传递进函数后,会解包,当作普通常数作为函数的parameter, will follow the rule, 多的丢掉,少了get nil, because you can call any function with any argument.
print(table.unpack({"Sun", "Mon", "Tue", "Wed"}, 2, 3)) --2,3 indicate which sequence unpack what to return
--> Mon Tue
Although the predefined unpack function is written in C, we could write it
also in Lua, using recursion:
function unpack (t, i, n)
i = i or 1
n = n or #t
if i <= n then
return t[i], unpack(t, i + 1, n)
end
end
--my test
function testFunctionPack(a,b,c,d,e)
print (a,b,c,d,e)--
end;
f=testFunctionPack;
para={1,2,3,4,5,5,6,6,7,7};
f(table.unpack(para)); --到底这种函数的使用方式有什么特别的用处的,,,
5.2 Variadic Functions
(动态参数)
function add (...)
local s = 0
for i, v in ipairs{...} do --注意要加{}构造table, 而不时iparirs(...).
s = s + v
end
return s
end
print(add(3, 4, 10, 25, 12)) --> 54
The three dots (...) in the parameter list indicate that the function is variadic.
When we call this function, Lua collects all its arguments internally; we call
these collected arguments the extra arguments of the function. A function can
access its extra arguments using again the three dots, now as an expression.
We call the expression ... a vararg expression. It behaves like a multiple
return function, returning all extra arguments of the current function. For
instance, the command print(...) prints all extra arguments of the function.
function TestVaridic(...)
print(...);--Notice: here no need to add {},because we don't need a table
end
Likewise, the next command creates two local variables with the values of the
first two optional arguments (or nil if there are no such arguments):
function TestVariaDic (...)
local a, b = ...
end
function foo (a, b, c)
to
function foo (...) -- which one do you prefer? actrually almost the same.
local a, b, c = ...
A function like the next one simply returns all arguments in its call:
function id (...) return ... end --It is a multi-value identity function.
The next function behaves exactly like another function foo, except that before the call it prints a message with its
arguments:
function foo1 (...)
print("calling foo:", ...)
return foo(...) --除了print out the argument 外,,功能还是在foo,so foo1 almost the same as foo
end
This is a useful trick for tracing calls to a specific function.Let us see another useful example.
Lua provides separate functions for formatting text (string.format) and for writing text (io.write). It is straightforward
to combine both functions into a single variadic function:
function fwrite (fmt, ...)
return io.write(string.format(fmt, ...))
end
Notice the presence of a fixed parameter fmt before the dots. Variadic functions can have any number of fixed parameters before the variadic part. (跟C 是一样的格式)
CALL PARAMETERS
fwrite() fmt = nil, no extra arguments
fwrite("a") fmt = "a", no extras
fwrite("%d%d", 4, 5) fmt = "%d%d", extras = 4 and 5
(Note that the call fwrite() raises an error, because string.format needs a
string as its first argument.)
In the rare occasions when the extra arguments can be valid nils (也就是... 里面可以有nil), however, the table created with {...} may not be a proper sequence. For instance, there is no way to detect in such a table whether there were trailing nils in the original arguments. For these occasions, Lua offers the table.pack function (New in Lua5.2)
This function receives any number of arguments and returns a new table with all
its arguments, just like {...}; but this table has also an extra field “n”, with the total number of arguments. The following function uses table.pack to test whether none of its arguments is nil:
function nonils (...)
local arg = table.pack(...) -- table.unpack 是解包成 逗号隔开的参数列表,而table.pack,这是将参数列表打包成table
for i = 1, arg.n do ---notice, table.pack(...), not table.pack({...}),no need to use {}
if arg[i] == nil then return false end
end
return true
end
print(nonils(2,3,nil)) --> false
print(nonils(2,3)) --> true
print(nonils()) --> true
print(nonils(nil)) --> false
Remember, however, that {...} is cleaner and faster than table.pack(...)
when the extra arguments cannot be nil.
5.3 Named Arguments
The parameter passing mechanism in Lua is positional: when we call a function,
arguments match parameters by their positions. The first argument gives the
value to the first parameter, and so on. Sometimes, however, it is useful to
specify the arguments by name.
let us consider the function os.rename (from the os library), which renames a file. Quite often, we forget which name comes first, the new or the old?
-- invalid code
rename(old="temp.lua", new="temp1.lua") -- 没有这语法
Lua has no direct support for this syntax, but we can have the same final effect,
with a small syntax change. The idea here is to pack all arguments into a table
and use this table as the only argument to the function. The special syntax that
Lua provides for function calls, with just one table constructor as argument,
helps the trick:
rename{old="temp.lua", new="temp1.lua"}
function rename (arg) --其实是没有原生的语法支持的,只是利用了table 的特点来达到而已,,,
return os.rename(arg.old, arg.new)
end
This style of parameter passing is especially helpful when the function has
many parameters and most of them are optional. For instance, a function that
creates a new window in a GUI library may have dozens of arguments, most of
them optional, which are best specified by names:
Listing 5.1. A function with named optional parameters:
function Window (options)
-- check mandatory options
if type(options.title) ~= "string" then
error("no title")
elseif type(options.width) ~= "number" then
error("no width")
elseif type(options.height) ~= "number" then
error("no height")
end
-- everything else is optional
_Window(options.title,
options.x or 0, -- default value
options.y or 0, -- default value
options.width, options.height,
options.background or "white", -- default
options.border -- default is false (nil)
)
end
w = Window{ x=0, y=0, width=300, height=200,
title = "Lua", background="blue",
border = true
}
======my verison========of window
function Window(opt)
if type (opt) ~='table' then
error "the parameter is send is not a table";
do return end; --Notice that in if ,elseif 是没有end 的,所以如果我们要跳出function,need to add do turn
elseif type (opt.title) ~='string' then ----
error "titlle is not a string";
do return end; ----in order to create a new block
elseif type (opt.height) ~='number' then
error "height is not a number"
do return end;
elseif type (opt.width) ~='number' then
error "width is not a number"
do return end;
else
_Window(opt.title,opt.x or 0, opt.y or 0, opt.width,opt.height,opt.background or "white",opt.border);
end;
end
Exercises
Exercise 5.1: Write a function that receives an arbitrary number of strings
and returns all of them concatenated together.
function concateString (...)
local argTable=table.pack(...);
local result='';
for i=1,argTable.n do --注意i 要赋初始值
if type(argTable[i]) ~='string' then
error ("the ".. i .. "parameter is not a string,please input string as parameter");
else
result=result..argTable[i];
end
end
return result;
end
print (concateString("1","2",'3','4'));
Exercise 5.2: Write a function that receives an array and prints all elements
in that array. Consider the pros and cons of using table.unpack in this function.
function printArray (a)
print (table.unpack(a));
end
printArray({1,2,3,4,5,'a','b',4});
Exercise 5.3: Write a function that receives an arbitrary number of values and
returns all of them, except the first one.
function returnAllArgexcpetFristOne(...)
local t={...};
local r={};
for i=2,#t do
r[i-1]=t[i];
end
return table.unpack(r);
end
print(returnAllArgexcpetFristOne(1,2,3,4,4,5,6,6));