chapter 5 Functions

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:

print "Hello World"  <--> print("Hello World")
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));


























 







































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值