V语言06函数
函数
V默认为纯函数,除了io无副作用.
这通过无全局变量及即使传递引用,函数参数默认不变,但V并非纯函数式语言.
编译器,有-enable-globals选项来启用全局变量,针对低级应用(内核,驱动).
可变参数
用变来允许参数可变:
struct User {
name string
mut:
is_registered bool
}
fn (mut u User) register() {
u.is_registered = 真
}//对象.`接收器`可变
mut user := User{}
println(user.is_registered) // "假"
user.register()
println(user.is_registered) // "真"
//其他参数也一样
fn multiply_by_2(mut arr []int) {//也要加变
for i in 0 .. arr.len {
arr[i] *= 2
}
}
mut nums := [1, 2, 3]
//也要加变
multiply_by_2(mut nums)
println(nums)
// "[2, 4, 6]"
最好返回值,而不是修改参数.在减少分配/复制时用参数返回.
因而V不允许修改作为参数的基本类型(如整),仅允许数组/映射可修改.
用user.register()或user=register(user)来替换register(mut user)
返回修改版的对象.
struct User {
name string
age int
is_registered bool
}
fn register(u User) User {
return {
...u//这样.
is_registered: true
}
}
mut user := User{
name: "abc"
age: 23
}
user = register(user)
println(user)
可变参数
fn sum(a ...int) int {
mut total := 0
for x in a {
total += x
}
return total
}//用...整来表可变
println(sum()) // 0
println(sum(1)) // 1
println(sum(2, 3)) // 5
// 分解数组
a := [2, 3, 4]
println(sum(...a)) // <--用...前缀来解包
b := [5, 6, 7]
println(sum(...b)) // output: 18
//C++是用后缀来解包.
匿名/高阶函数:
fn sqr(n int) int {
return n * n
}
fn cube(n int) int {
return n * n * n
}
fn run(value int, op fn (int) int) int {
return op(value)
}//函数.前面为值,后面为类型.
fn main() {
//函数可传递给其他函数
println(run(5, sqr)) // "25"
//λ函数可在其他函数中定义/声明
double_fn := fn (n int) int {
return n + n
}
println(run(5, double_fn)) // "10"
//不赋值变量下传递函数
res := run(5, fn (n int) int {
return n + n
})
println(res) // "10"
//函数数组/映射
fns := [sqr, cube]
println(fns[0](10)) // "100"
fns_map := map{
"sqr": sqr
"cube": cube
}
println(fns_map["cube"](2)) // "8"
}
引用
struct Foo {}
fn (foo Foo) bar_method() {
// ...
}
fn bar_function(foo Foo) {
// ...
}
函数参数不变,则由编译器决定是值/引用传递,不用记按引用/值传递.加上&确保总是按引用传递:
struct Foo {
abc int
}
fn (foo &Foo) bar() {//&按引用.
println(foo.abc)
}//`foo`仍是不变的,否则用(mut foo Foo)
V引用类似Go指针/C++引用.通用树:
struct Node<T> {
val T
left &Node<T>
right &Node<T>
}
常数
const (
pi = 3.14
world = "世界"
)//用`常`来定义`常数`.这里声明多个常.
println(pi)
println(world)
只能在模块级别定义常数.这个常是不变的意思.
也可const e = 2.71828单独声明常.
V常更灵活,你可赋值多个复杂值.
struct Color {
r int
g int
b int
}
fn rgb(r int, g int, b int) Color {
return Color{
r: r
g: g
b: b
}
}
const (//多个赋值
numbers = [1, 2, 3]
red = Color{
r: 255
g: 0
b: 0
}
// 编译时求值-->现在是启动时程序求值了.
blue = rgb(0, 0, 255)
)//相当于一个区块了.
println(numbers)
println(red)
println(blue)
禁止全局变量,因而用常块.用公可导出常数.
module mymodule
pub const golden_ratio = 1.61803
fn calc() {
println(mymodule.golden_ratio)
}
常块(常())前面不能有公.外部用常,必须加模块名.
常量用snake_case,为区别本地变量,要加模块名.为用π,内外都要用math.pi.只在主模块中放松,由vfmt考虑,你在数学模块中用pi最后会加上数学.
println(pi)//变成
println(math.pi)
内置函数
下为完整列表
fn print(s string) //输出中打印
fn println(s string) //打印并加换行
fn eprint(s string) //输出在错误
fn eprintln(s string) //
fn exit(code int) //用自定义错误码退出程序
fn panic(s string) //错误中打印消息并跟踪,用1错误码退出
fn print_backtrace() //打印跟踪栈
打印,可打印strings,numbers,arrays,maps,structs.
struct User {
name string
age int
}
println(1) // "1"
println("hi") // "hi"
println([1, 2, 3]) // "[1, 2, 3]"
println(User{ name: "Bob", age: 20 }) // "User{name:"Bob", age:20}"
//自定义,加个`串`函数
struct Color {
r int
g int
b int
}
pub fn (c Color) str() string {
return "{$c.r, $c.g, $c.b}"
}
red := Color{
r: 255
g: 0
b: 0
}
println(red)
根目录下所有文件,均为相同模块的部分.简单程序不必指定模块名,默认为主.
V是模块化语言,鼓励创建可重用模块,
// myfile.v之上为mymodule目录
module mymodule
//导出用公
pub fn say_hi() {
println("我的模块,你好")
}
//外部使用
import mymodule
fn main() {
mymodule.say_hi()
}
序号 | 注意 |
|---|---|
1 | 模块名要短,<10个符. |
2 | 用snake_case格式 |
3 | 禁止循环导入 |
4 | 所有模块静态编译至exe文件 |
模块的初化函数
fn init() {
//模块级初化代码,初化C库很有用.
}//抄的D的静态模块构造,可为公,自动调用该函数
浙公网安备 33010602011771号