Nim教程【十一】

liulun發表於2015-06-17

引用型別和指標型別

不同的引用可以只想和修改相同的記憶體單元

在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?

 

相關文章