数组
数组是一个整型数值作为索引的值的序列,其索引从0到数组大小减1.数组元素可以通过它的索引进行取值。
local a=[“I’m a string”, 123] print(typeof a[0]) //prints "string" print(typeof a[1]) //prints "integer"
可以通过一系列的内置函数对数组进行改变大小,插入和删除操作。
函数
函数和字符串活整型类型一样属于第一类值,可以被保存在表的槽中,局部变量,数组以及以函数参数的进行传递。函数可以在Squireel中或者在本地语言中实现,通过与ANSIC兼容的形式进行调用。
函数声明
函数可以通过函数表达式进行声明:
local a= function(a,b,c) {return a+b-c;}或者语法糖:function ciao(a,b,c) { return a+b-c; }它等价于:this.ciao <- function(a,b) { return a+b-c; }也可以用以下的方式声明:T <- {} function T::ciao(a,b,c) { return a+b-c; } //这个等价于 T.ciao <- function(a,b,c) { return a+b-c; } //或者 T <- { function ciao(a,b,c) { return a+b-c; } }默认参数Squireel可以含有默认参数。含有默认参数的函数可以以以下形式声明:function test(a,b,c = 10, d = 20) { .... }当函数被调用,并且没有指定b,c参数,虚拟机会自动给未指定的参数赋默认的值。默认参数可以是任意有效地Squireel表达式。表达式在运行时计算。不定参数Squireel函数可以含有任意数量的参数(varargs函数)。varargs函数通过在参数列表后面添加三个点实现。
当函数被调用的时候,所有额外的参数可以通过假数组”vargv“访问。
vargv的索引只能是整型或浮点型。vargv的大小存在在假变量vargc中。
注意:vargv不是真实的对象。不能被传递或赋值。function test(a,b,...) { for(local i = 0; i< vargc; i++) { ::print("varparam "+i+" = "+vargv[i]+"/n"); } } test("goes in a","goes in b",0,1,2,3,4,5,6,7,8);
函数调用
exp:= derefexp ‘(‘ explist ‘)’
表达式的调用顺序是:derefexp将后于
explist调用。
每一个函数的调用,Squireel都会隐含的传递一个环境对象参数”this“给被调用的函数。这个”this“参数就是干函数索引处的对象。如果用以下语法调用:table.foo(a)传递给foo的环境对象就是”table“.foo(x,y) // 等价于 this.foo(x,y)这个环境对象就是”this“(和他的调用者一样)。向函数绑定环境在默认情况下,Squireel向函数传递一个环境对象"this",函数索引所在的对象。然而,可以通过内置的方法"closure.bindenv(env_obj)"静态的绑定一个环境给闭包,该函数返回一个新的含有环境绑定的闭包对象。当向函数绑定了一个环境对象,该函数每一次调用,其环境对象将是上一次绑定的环境。这种机制有助于实现类似于C#委托的回调系统。注意:闭包对象含有被绑定对象的弱引用,因此,如果这个环境对象被删除,那么下一次调用,这个闭包包含的环境对象将会返回null。自用变量自用变量被函数引用,但是在函数作用域中不可见的变量。下面的例子,函数foo声明了x,y但是testy是一个自由变量。自用的变量的值在函数创建的时候后被冻结并且绑定到该函数。自用变量在函数每次调用的时候作为默认隐含参数进行传递。尾递归尾递归是一种部分的将程序中的递归转会为迭代的方法。它用在尾递归作为函数中最后一个执行体(仅在return之前)的情况下。如果发生这种情况,Squireel的预编译器将会在尾递归调用前将调用站的帧展开。因为深层次的递归调用可能导致栈溢出。