openarray型別
注意:openarray型別只能用於引數
固定大小的陣列雖然效能不錯,但過於呆板,使用取來不是很方便
對於一個方法來說,傳入引數如果是一個陣列,最好是不要限制陣列的長度
也就是說,方法應該能夠處理不同大小的陣列
openarray型別就是為了滿足這樣的要求而設計的
openarray型別的變數索引總是從0開始
len、low、high等操作同樣試用於openarray型別
原則上,任何一個陣列都可以被傳遞到一個openarray引數中,索引的型別並不重要
但是一定要注意:不能給openarray型別的引數傳遞多維陣列
可變數量的引數
一個可變數量的引數就是一個openarray引數
他可以讓開發者傳遞多個同一型別的引數給一個方法
編譯器自動將這些引數轉換為一個openarray陣列
proc myWriteln(f: File, a: varargs[string]) = for s in items(a): write(f, s) write(f, "\n") myWriteln(stdout, "abc", "def", "xyz") # is transformed by the compiler to: myWriteln(stdout, ["abc", "def", "xyz"])
需要注意的是:這種型別的引數必須是方法簽名的最後一個引數
另外,你可以通過下面這種方式來動態轉換傳入的引數的型別
proc myWriteln(f: File, a: varargs[string, `$`]) = for s in items(a): write(f, s) write(f, "\n") myWriteln(stdout, 123, "abc", 4.0) # is transformed by the compiler to: myWriteln(stdout, [$123, $"def", $4.0])
在這個例子中,$應用於任何引數,
(注意:$應用於字串時,是一個nop操作)
(譯者注:這個語言特性非常像C#裡的param關鍵字)
slice型別
slice型別和subranges型別很相似
但這兩個型別的使用場景不盡相同
在實際的業務控制程式碼中slice型別並不是很常用
但在很多集合型別的操作中,slice起到定義運算元的作用
請看下面的程式碼:
var a = "Nim is a progamming language" b = "Slices are useless." echo a[7..12] # --> 'a prog' b[11.. -2] = "useful" echo b # --> 'Slices are useful.'
在上面的例子中,slice型別被用於修改一個字串的一部分
在上面的例子中,-2是一個負數索引(倒數第二個字元)
理論上slice可以容納任何型別的資料
但是如果slice用於方法的簽名中,則必須明確slice容納的資料型別
Tuple元組型別
Tuple元組型別定義了一系列的有序的屬性
可以使用方括號來定義元組,
使用小括號來構造元組,
構造器中屬性的順序必須和元組定義的屬性的順序一致
如果兩個元組在定義的時候,使用了相同的屬性而且屬性的順序也是一致的
那麼這兩個元組就是相同的
可以使用t.field來訪問一個元組的某個屬性
也可以使用t[i]來訪問一個元組的第幾個屬性
來看下面的程式碼:
type Person = tuple[name: string, age: int] # type representing a person: # a person consists of a name # and an age var person: Person person = (name: "Peter", age: 30) # the same, but less readable: person = ("Peter", 30) echo(person.name) # "Peter" echo(person.age) # 30 echo(person[0]) # "Peter" echo(person[1]) # 30 # You don't need to declare tuples in a separate type section. var building: tuple[street: string, number: int] building = ("Rue del Percebe", 13) echo(building.street) # The following line does not compile, they are different tuples! #person = building # --> Error: type mismatch: got (tuple[street: string, number: int]) # but expected 'Person' # The following works because the field names and types are the same. var teacher: tuple[name: string, age: int] = ("Mark", 42) person = teacher
從上面的程式碼中,大家可以看出
在使用tuple型別的時候,不一定要新建立一個型別出來
上面的程式碼中的building變數就直接使用了tuple型別,而不像person一樣先建立了一個Person型別
只有在元組屬性賦值期間元組才可以被拆箱(這裡不知道翻譯的對不對,原文:Tuples can be unpacked during variable assignment (and only then!).)
os模組的內建splitFile方法,可以返回三個值,一個是路徑,一個是檔名,一個是副檔名
這個時候就可以應用這個特性
import os let path = "usr/local/nimc.html" (dir, name, ext) = splitFile(path) baddir, badname, badext = splitFile(path) echo dir # outputs `usr/local` echo name # outputs `nimc` echo ext # outputs `.html` # All the following output the same line: # `(dir: usr/local, name: nimc, ext: .html)` echo baddir echo badname echo badext
上面的程式碼第一次輸出和第二次輸出是一樣的
只有使用var或者let操作符時,才可以應用元組解包的特性
下面的程式碼編譯不會通過的
import os var path = "usr/local/nimc.html" dir, name, ext = "" (dir, name, ext) = splitFile(path) # --> Error: '(dir, name, ext)' cannot be assigned to
今天就寫到這裡吧,喜歡的請幫忙點個推薦
謝謝大家