【Nim】高级数据类型

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/aqtata/article/details/82586702

一、枚举类型

type
    Day = enum
        Monday, Tuesday, Wednesday

var d = Monday
echo d  # Monday

d = Day(1)
echo d  # Tuesday

和其他语言一样,枚举类型第一个元素值默认从0开始,逐渐+1,但也可以自己指定值

type
    Day = enum
        Monday = 5, Tuesday, Wednesday = 10

var d = Monday
echo ord(d)  # 5

d = Tuesday
echo ord(d)  # 6

二、有序类型

有序类型不是值一个具体的类型,是泛指内存中用数字存储的类型,比如int、bool、char、enum

var b = false

# ord方法得到对应的整数值
echo ord(b)

# inc方法将值+1
inc(b)
echo b # true

# 超出了bool可接受的范围,会引发OverflowError异常
#inc(b)

type
    Day = enum
        Monday, Tuesday, Wednesday

var d = Wednesday
dec(d) # 与inc相反,将值-1
echo d # Tuesday

# pred和dec一样,但返回一个新值
var d2 = pred(d)
echo d2

# succ和inc一样,但返回一个新值
d2 = succ(d2, 2)
echo d2 # Wednesday

inc、dec、succ、pred都支持第2个参数,指定一个跨度

var n = 0
echo n # 0

inc(n, 5)
echo n # 5

dec(n, 2)
echo n # 3

n = succ(n, 7)
echo n # 10

n = pred(n, 2)
echo n # 8

三、范围值

范围值需要自己定义,强制只接受范围内的值

type
    MyRange = range[0..5]

var r: MyRange = 0
echo r

inc(r, 2)
echo r

上面这个例子自定义了一个MyRange类型,只接受0到5的数值

四、集合类型

集合类型用花括号构造"{}"

var
    x: set[char] = {'a'..'f', '0'..'5'}
    y = {'0'..'9'}

echo x # {'0', '1', '2', '3', '4', '5', 'a', 'b', 'c', 'd', 'e', 'f'}
echo y # {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}

# 合并集合
echo x + y # {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}

# 交集
echo x * y # {'0', '1', '2', '3', '4', '5'}

# x不包含y的集合
echo x - y # {'a', 'b', 'c', 'd', 'e', 'f'}

# 集合是否相等
echo x == y  # false

# x是否是y的子集,或相等
echo x <= y  # false

# x集合中是否包含元素'z'
echo 'z' in x # false

# x集合中是否不包含元素'z'
echo 'z' notin x # true

# x集合中是否包含元素'z',同in一样
echo x.contains('z') # false

# 元素数量
echo y.card # 10

# 添加元素
incl(x, '6')
echo x # {'0', '1', '2', '3', '4', '5', '6', 'a', 'b', 'c', 'd', 'e', 'f'}

# 删除元素
excl(x, '0')
echo x # {'1', '2', '3', '4', '5', '6', 'a', 'b', 'c', 'd', 'e', 'f'}

五、数组类型

数组长度是固定的,无法改变,使用方括号"[]"

type
    IntArray = array[1..5, int] # 下标从1开始,元素数量为5个

var arr: IntArray
arr = [5,10,15,20,25]
for index, val in arr:
    echo "Index: ", index, " Value = ", val

输出结果

Index: 1 Value = 5
Index: 2 Value = 10
Index: 3 Value = 15
Index: 4 Value = 20
Index: 5 Value = 25

或者直接指定长度,下标默认从0开始

type
    IntArray = array[5, int] # 下标从0开始,元素数量为5个

var arr: IntArray
arr = [5,10,15,20,25]
for index, val in arr:
    echo "Index: ", index, " Value = ", val

echo low(arr)   # 最小下标0
echo high(arr)  # 最大下标4
echo len(arr)   # 数组长度
echo repr(arr)  # 打印数组内容 [5,10,15,20,25]

六、seq类型

seq类型其实就是动态数组

var arr: seq[int] # 不用指定size,默认为nil
echo arr

arr = @[5,10]  # 赋值方式和数组一样用[],只是前面多了个@符号
echo arr

arr.add(15)  # 添加元素
echo arr # [5, 10, 15]

arr.del(0) # 删除元素
echo arr # [10, 15]

arr.insert(5, 1) # 在索引1处插入元素5
echo arr # [15, 5, 10]


var
    x: seq[int]

newSeq(x, 10) # 用newSeq方法生成指定长度的seq
echo x

七、OpenArray

怎么又来了个数组呢?别怕,它只能用在函数参数中,来个反面教材

proc foo(arr: array[3, int]): int = arr.len

var
    arr: array[4, int] = [5,10,15,20]

echo foo(arr) # 类型不匹配

因为在Nim中,array类型必须指定长度,如果一个函数要接受array类型也必须指定长度,但是这样就没法处理任意长度的数组了,所以在这里可以用OpenArray类型来解决

proc foo(arr: openArray[int]): int = arr.len

var
    arr: array[4, int] = [5,10,15,20]

echo foo(arr)

八、切片

切片就是对另一个数据进行截取,是一种特性

var
    a = "hello world!"

# 以下三句效果是一样的
echo a.substr(0, 5) # hello
echo a[0..4]        # hello
echo a[..4]         # hello

# 以下三句效果是一样的
echo a.substr(6, a.len - 1)  # world!
echo a[6..a.len - 1]         # world!
echo a[6..^1]                # world!

# 替换字符串
a[0..4] = "123456789"
echo a

九、元祖类型

元祖类型用圆括号"()"来构造

var
    person: tuple[name: string, age: int]

person = (name: "jack", age: 18)
echo person

作为函数返回值时,可以分开接受

proc foo(): tuple[name: string, age: int] = 
    result = (name: "jack", age: 18)

let
    (name, age) = foo() # 用圆括号接受拆包后的值

echo name # jack
echo age  # 18

十、引用和指针

自定义一个对象,可以理解为C语言中的结构体

type
    MyObj = object
        name: string
        age: int

var obj: MyObj
echo sizeof(obj) # sizeof(name) + sizeof(age) = 8

obj是在栈上分配的内存,类似于C语言中结构体,随着成员变量的增加,size也会增加。

通过ref关键字用来声明一个引用类型,引用类型是可以被自动回收的,不用担心内存泄漏问题

type
    MyObj = object
        name: string
        age: int

var obj: ref MyObj # 引用类型,默认为nil
echo sizeof(obj) # size = 4

if (obj == nil):
    echo "obj == nil"

obj = new MyObj  # 通过new来创建实例
obj.name = "jack"
echo obj.name

而用ptr声明的类型是不会被Nim回收的,此时就像在写C代码一样,自己要注意释放问题

type
    MyObj = object
        name: string
        age: int

var obj: ptr MyObj # nil
echo sizeof(obj) # size = 4

if (obj == nil):
    echo "obj == nil"

obj = cast[ptr MyObj](alloc(sizeof(MyObj)))
obj.name = "jack"
echo obj.name
dealloc(obj) # 类似C语言中delete,需要手动释放内存

参考:

https://nim-lang.org/docs/tut1.html#advanced-types

猜你喜欢

转载自blog.csdn.net/aqtata/article/details/82586702