函數在倉頡語言中是普遍存在的。通過之前的章節已經可以瞭解到倉頡函數的基本形式: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。
參考引用
- 免費開源書《跟老衞學倉頡編程語言開發》
- 免費開源書《跟老衞學HarmonyOS開發》
- HarmonyOS NEXT+AI大模型打造智能助手APP(倉頡版)(視頻)
- 倉頡編程從入門到實踐(北京大學出版社)