函数和方法(function & method)
河图中的函数使用不同的关键字来声明,这代表了函数的类型,例如:fun, get, set, construct, factory。
函数声明的每一个部分都可能省略。如果省略了参数列表,则连参数列表的空括号也可以不用写。
fun doubleIt(n: num) -> num {
return n * 2
}
fun main {
def x = doubleIt(7) // expect 14
print(x)
}
函数定义的语句块中也可以定义函数和类。
函数在河图中是一等公民,可以将其当做表达式求值,也可以作为参数传递。
fun closure(func) {
var i = 42
fun nested {
i = i + 1
return(func(i))
}
return nested
}
fun main {
var func = closure( (n) => n * n )
print(func()) // print: 1849
print(func()) // print: 1936
}
单行函数
和 Dart 一样,你可以使用 '=>' 来定义以一个表达式作为定义的函数:
var func = (x) => x * x
final sq = func(4) // sq = 16
可选参数
和 Dart 一样,你可以使用可选位置参数,或者可选命名参数。并且也可以为其指定默认值。和 Dart 的不同之处在于,对于提供了默认值的参数,只要传递进来的值是 null,都会使用默认值来替换。
fun posParam(a, [b = 7]) {
return a * b
}
final r1 = posParam(6) // r1 = 42
fun namedParam({a = 3, b = 9}) {
return a * b
}
final r2 = namedParam(b: 10) // r2 = 30
变长参数列表
使用 '...' 来定义一个变长参数列表。此时这个函数可以接受任意长度的参数数量。在函数定义中,这个变长参数的名字将会以一个包含全部剩余参数的 List 作为它的值。
external fun print(... args: any)
print('hello', 'world!', 42) // okay!
省略参数名
你可以用 '_' 来省略某个参数的名字。这在某些函数式编程的场合有用,某些函数的实现用不到某些参数。
fun test1(expect, value, [arg]) {
print('running test1 with ${arg}: expect ${expect}, value ${value}')
}
fun test2(_, value, [_]) {
print(value)
}
fun run(expect, value) {
test1(expect, value, 'test1')
test2(expect, value, 'test2')
}
函数的返回值
如果函数定义中没有显式提供 return 语句,函数将会返回最后一行语句的求值(可能为 null)。
匿名函数(也叫函数表达式,函数字面量或者 lambda)
fun closure(func) {
var i = 42
fun nested () {
i = i + 1
print(func(i))
}
return nested
}
var func = closure( (n) => n * n )
func()
函数表达式和普通的函数声明的不同之处在于。函数关键字也可以省略,但此时不能省略参数列表的括号。下面五种函数字面量都是合法的:
final func0 = fun meaning { return 42 }
final func1 = fun { return 42 }
final func2 = fun => 42
final func3 = () { 42 }
final func4 = () => 42
立即执行的匿名函数
匿名函数本质上是个表达式,因此他可以求值,因此也可以立即对其进行函数执行:
() {
return Future( () => 42 )
} ().then(
(value){
print(value)
}
)
print(41)
上面的例子中,在一个匿名函数中创建了一个Future对象,然后立即执行这个匿名函数并使用 then() api绑定了一个回调函数。 最终执行结果是先打印41,然后再打印42。
匿名函数和 struct 的交互
bind()
bind 可以获得一个新的匿名函数,并且新函数是这个 struct 的成员函数。函数定义中的 this 将会绑定到这个 struct 上。这在某些需要分离逻辑和数据的场合比较有用。
final obj = {
name: 'nobody'
}
final func = () {
this.name = 'foobar'
}
final newfunc =func.bind(obj)
newfunc()
print(obj.name) // 'foobar'
apply()
apply 和 bind() 类似,但只是一次性的将这个函数绑定到这个 struct 并立即调用,并不会获得新函数,也不会修改原来的函数。
final obj = {
name: 'nobody'
}
final greeting = () {
print('Hi! I\'m ${this.name}')
}
greeting.apply(obj)