--- title: 初試新的編譯程式語言 V (二) - 函式 & 變數 description: V - 用於開發可維護性軟體的簡單,快速,安全的編譯語言。 # image: https://hackmd.io/screenshot.png tags: V,vlang # robots: noindex, nofollow langs: zh_Hant --- # 初試新的編譯程式語言 V (二) - 函式 & 變數 V是一種靜態類型的編譯編程語言,用於構建可維護的軟件。它與Go類似,也受到Oberon,Rust,Swift的影響。 ## Hello World **hell_world.v**: ```v // 這是單行註解 /* 這是多行註解 */ /* - `fn` 關鍵字 用來宣告函式(funciton) - `fn main() {...}` 執行檔進入點 */ fn main() { println('hell world') // 內建函式。它將值打印到標準輸出。 } ``` 要在V的程式碼中撰寫單行註解,以`//`開始;多行註解以`/*`開始並以`*/`結尾。 要宣告函式必須使用`fn`。返回型別在函式名稱後面宣告。在上方情況下,`main`不返回任何內容,因此省略了型別宣告。 要將值打印到標準輸出,可以調用`println`內建函式。 `fn main()`宣告可以在擔一個文件的程式中忽略。這在編寫小程序,“腳本(script)”或只是學習語言時很有用。 **hell_world.v**: ```v println('hell world') ``` > 在終端執行`v run hell_world.v`,會編譯成並自動執行hell_world.exe ## 函式 (Fuctions) **functions.v**: ```v fn main() { // 主函式 調用 下方的函式 println('add(77, 33)') println(add(77, 33)) println('sub(100, 50)') println(sub(100, 50)) println('mul(8, 8)') println(mul(8, 8)) } /* - 函式參數名稱 在 函式名稱 後的`()`中宣告 - 函式參數型別 在 函式參數名稱 後宣告 - 函式返回型別 在 函式名稱 後的`()`之後宣告 */ fn add(x int, y int) int { return x + y } // 一樣的函式參數型別可以只宣告一次 fn sub(x, y int) int { return x - y } fn mul(x, y int) int { return x * y } ``` 型別的宣告需出現在參數的名稱之後。就像在Go和C中一樣,函式不能重載。 函式可以在宣告之前調用:`add`,`sub`和`mul`在`main`之後宣告,但仍然可以從`main`調用。 **functions.v**執行結果: ``` add(77, 33) 110 sub(100, 50) 50 mul(8, 8) 64 ``` ## 變數 (Variables) **variables.v**: ```v // 宣告並初始化一個字串(String)變數 name := 'Bob' // 宣告並初始化一個整數(Integer)變數 age := 20 /* 型別轉換 `T(v)` 宣告並初始化一個64位元有號整數(64 bits signed integer)變數 */ large_number := i64(9999999999) println(name) println(age) println(large_number) ``` 宣告一個變數的唯一方法是使用`:=`來初始化變數的值。 變數的型別是編譯器從右側的值推斷出來的。 要強制使用其他型別,請使用型別轉換:表達式`T(v)`將值`v`轉換為型別`T`. V只允許在函式中定義變數。V沒有全域狀態(模組級別)的變數。 **variables.v**執行結果: ``` Bob 20 9999999999 ``` 在V中,**默認情況下變數是不可變的(immutable)**,意思指只使用`:=`將變數初始化後,變數的值將不能進行改變。 要更改變數,必須在變數名稱前使用`mut`宣告,並使用`=`來分配(assign)值給它 **mut_var.v** ```v // 將mut刪除後嘗試編譯會出現錯誤 mut age := 20 println(age) age = 21 println(age) ``` 將mut刪除後嘗試編譯會出現錯誤: ``` mut_var.v : 4:5: `age` is immutable. ``` **注意:`:=`用於宣告和初始化,`=`用於分配。** ```v fn main() { // 代碼不會被編譯成功,因為未宣告變數age。 age = 21 } ``` 編譯錯誤: ``` test.v:2:4: undefined: `age` ``` 宣告一個變數但之後**未調用該變數**會導致編譯錯誤,如下: ```v fn main() { // 代碼不會被編譯成功,因為未調用變數age。 age := 21 } ``` 編譯錯誤: ``` test.v:2:0: `age` declared and not used ``` 在V中,**不允許使用變數遮蔽(variable shadowing)**。在子作用域宣告的變數若具有已在父作用域中使用的名稱,將導致編譯錯誤。 ``` fn main() { // 父作用域 a := 10 if true { // 子作用域 a := 20 // 不允許使用變數遮蔽 } } ``` 編譯錯誤: ``` test.v:4:6: redefinition of `a` ```