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个符.
2snake_case格式
3禁止循环导入
4所有模块静态编译至exe文件

模块的初化函数

fn init() {
	//模块级初化代码,初化C库很有用.
}//抄的D的静态模块构造,可为公,自动调用该函数
posted @   zjh6  阅读(18)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示