为了账号安全,请及时绑定邮箱和手机立即绑定

跟老卫学仓颉编程语言开发:函数

函数在仓颉语言中是普遍存在的。通过之前的章节已经可以了解到仓颉函数的基本形式:main()函数是很多程序的入口点,func关键字用来声明函数。

本节将初步探讨函数,内容包括定义函数、函数参数、函数返回值等。在第11章还会对函数进行深入的讲解。

本节示例可以在“function_demo”应用下找到。

定义函数

仓颉使用关键字func来表示函数定义的开始,func之后依次是函数名、参数列表、可选的函数返回值类型、函数体。其中,函数名可以是任意的合法标识符,参数列表定义在一对圆括号内(多个参数间使用逗号分隔),参数列表和函数返回值类型(如果存在)之间使用冒号分隔,函数体定义在一对花括号内。

以下是一个自定义函数的示例:

// main函数是程序入口
main() {
    // 执行函数
    println_hello();
}

// 自定义函数
func println_hello() {
    // 打印Hello World!
    println("Hello World!");
}

上述示例脱胎于“Hello World”应用,只是将打印字符串的逻辑封装到了自定义函数println_hello中。上述例子执行之后输出内容如下:

Hello World!

定义函数需要注意以下几点:

  • 函数名和变量名使用蛇形命名法(snake case),例如println_hello();
  • 函数的位置可以随便放;
  • 如果函数定义了参数,则参数都需要标注类型。

函数参数

仓颉是强类型语言,因此如果函数定义了参数,则参数都需要标注类型,例如:

// main函数是程序入口
func main() {
    // 执行函数传递参数
    let text = 999;
    println_text(text);
}

// 如果函数定义了参数,则参数都需要标注类型
func println_text(text: Int64) {
    println("text: ${text}");
}

上述例子中,println_text函数有一个参数类型是Int64。上述例子执行之后输出内容如下:

text: 999

一个函数可以拥有0个或多个参数,这些参数均定义在函数的参数列表中。根据函数调用时是否需要给定参数名,可以将参数列表中的参数分为两类:非命名参数和命名参数。

非命名参数的定义方式是p: T,其中p表示参数名,T表示参数p的类型,参数名和其类型间使用冒号连接。例如,以下add函数的两个参数a和b均为非命名参数。

func add(a: Int64, b: Int64): Int64 {
    return a + b;
}

命名参数的定义方式是p!: T,与非命名参数的不同是在参数名p之后多了一个“!”。可以将上例中add函数的两个非命名参数修改为命名参数,如下所示:

func add(a!: Int64, b!: Int64): Int64 {
    return a + b
}

命名参数还可以设置默认值,通过“p!: T = e”方式将参数p的默认值设置为表达式e的值。例如,可以将上述add函数的两个参数的默认值都设置为1:

func add(a!: Int64 = 1, b!: Int64 = 1): Int64 {
    return a + b
}

:只能为命名参数设置默认值,不能为非命名参数设置默认值。

参数列表中可以同时定义非命名参数和命名参数,但是需要注意的是,非命名参数只能定义在命名参数之前,也就意味着命名参数之后不能再出现非命名参数。例如,下例中add函数的参数列表定义是不合法的:

// 错误!命名参数之后不能再出现非命名参数
func add(a!: Int64, b: Int64): Int64 {
    return a + b
}

上述函数会报如下错误:

error: unnamed parameters must come before named parameters
  ==> main.cj:39:21:
   |
39 | func add(a!: Int64, b: Int64): Int64 {
   |          ~~~~~~~~~  ^^^^^^^^ unexpected unnamed parameter here
   |          |
   |          because it must come before this named parameter
   |

1 error generated, 1 error printed.

函数参数均为不可变变量,在函数定义内不能对其赋值。

func add(a: Int64, b: Int64): Int64 {
    a = a + b // 错误!
    return a
}

函数参数作用域从定义处起至函数体结束:

func add(a: Int64, b: Int64): Int64 {
    var a_ = a // 正确
    var b = b  // 错误!
    return a
}

函数返回

函数返回值类型是函数被调用后得到的值的类型。函数定义时,返回值类型是可选的:可以显式地定义返回值类型(返回值类型定义在参数列表和函数体之间),也可以不定义返回值类型,交由编译器推导确定。

当显式地定义了函数返回值类型时,就要求函数体的类型、函数体中所有return e表达式中e的类型是返回值类型的子类型,否则则会因为类型不匹配而报错。

以下是一个函数返回的例子:

// main函数是程序入口
main() {
    // 获取函数的返回值
    let a: Int64 = 1;
    let b: Int64 = 1;
    let add_result = add(a, b);
    println("add result: {add_result}");
}

// 定义带返回的函数
func add(a: Int64, b: Int64): Int64 {
    return a + b;
}

上述例子中,add函数有两个参数类型都是Int64,该函数会返回Int64类型的值。在函数定义时如果未显式定义返回值类型,编译器将根据函数体的类型以及函数体中所有的return表达式来共同推导出函数的返回值类型。例如,上述例子中add函数的返回值类型可以被省略,但编译器仍然可以根据return a + b推导出add函数的返回值类型是Int64。

返回的值用关键字return标识。如果返回的值,是函数的最后一行,那么也可以不需要关键字return,示例如下:

// 定义带返回的函数
func add(a: Int64, b: Int64): Int64 {
    // 等同于 
    // return a + b;
    a + b
}

上述例子执行之后输出内容如下:

add result: 2

:函数的返回值类型并不是任何情况下都可以被推导出来的,如果返回值类型推导失败,编译器会报错。指定返回类型为Unit时,编译器会在函数体中所有可能返回的地方自动插入表达式return (),使得函数的返回类型总是为Unit。

参考引用

图片描述

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
全栈工程师
手记
粉丝
1.7万
获赞与收藏
2192

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

举报

0/150
提交
取消