引用型別和指標型別
不同的引用可以只想和修改相同的記憶體單元
在nim中有兩種引用方式,一種是追蹤引用,另一種是非追蹤引用
非追蹤引用也就是指標,指向手動在記憶體中分配的物件;
追蹤引用指向一個垃圾收集的物件;
非追蹤引用是不安全的
然而對於一些低階操作(比如說訪問硬體),非追蹤引用是不可避免的
追蹤引用用ref關鍵詞宣告
非追蹤引用用ptr關鍵詞宣告
可以用[]來解包一個引用(訪問一個元組或物件域時要用到)
請看下面的程式碼:
type Node = ref NodeObj NodeObj = object le, ri: Node data: int var n: Node new(n) n.data = 9 # no need to write n[].data; in fact n[].data is highly discouraged!
上面程式碼中最後一行,沒必要寫成n[].data
使用new()來建立一個新的追蹤物件
可以使用alloc或dealloc或realloc函式處理非追蹤物件
如果一個引用沒有指向任何東西,那麼他的值為nil
proc方法指標型別
方法型別是一個方法的指標
(譯註:一般函式式的語言中都有這個特性哦)
方法型別的變數預設值為nil
來看一下下面的程式碼
proc echoItem(x: int) = echo(x) proc forEach(action: proc (x: int)) = const data = [2, 3, 5, 7, 11] for d in items(data): action(d) forEach(echoItem)
模組
nim允許把一個程式分成若干個模組
一個模組就是一個檔案
模組可以起到隱藏資訊的作用(譯註:物件導向的封裝)
模組可以起到分開編譯的作用
一個模組可以用import語句匯入另一個模組的符號
在一個模組中,只有用星號標記的符號,才能匯出給另一個模組
來看看下面的程式碼:
# Module A var x*, y: int proc `*` *(a, b: seq[int]): seq[int] = # allocate a new sequence: newSeq(result, len(a)) # multiply two int sequences: for i in 0..len(a)-1: result[i] = a[i] * b[i] when isMainModule: # test the new ``*`` operator for sequences: assert(@[1, 2, 3] * @[1, 2, 3] == @[1, 4, 9])
在這個模組檔案中匯出了變數x和方法*
在程式開始執行的時候就會執行模組的頂層語句,
程式設計師可以利用nim的這個特性來初始化一些複雜的資料結構
模組的內部可以通過使用isMainModule內建變數來判斷當前模組是否為主模組
來看看下面兩個模組的程式碼:
# Module A type T1* = int # Module A exports the type ``T1`` import B # the compiler starts parsing B proc main() = var i = p(3) # works because B has been parsed completely here main() # Module B
import A # A is not parsed here! Only the already known symbols # of A are imported. proc p*(x: A.T1): A.T1 = # this works because the compiler has already # added T1 to A's interface symbol table result = x + 1
模組的符號的書寫要符合module.symbol的語法
如果一個符號在兩個模組中都定義過了
而且第三個模組引用了這兩個模組
來看看下面三個模組的程式碼:
# Module A var x*: string
# Module B var x*: int# Module C
import A, B write(stdout, x) # error: x is ambiguous write(stdout, A.x) # no error: qualifier used var x = 4 write(stdout, x) # not ambiguous: uses the module C's x
但這個規則並不適用於方法或迭代器
對於方法或迭代器來說,適用於過載的規則
來看看下面的程式碼:
# Module A proc x*(a: int): string = $a# Module B proc x*(a: string): string = $a# Module C import A, B write(stdout, x(3)) # no error: A.x is called write(stdout, x("")) # no error: B.x is called proc x*(a: int): string = nil write(stdout, x(3)) # ambiguous: which `x` is to call?