Refresh December 2018 Views 1.2k time
5

Just started programming in the Nim language (which I really like so far). As a learning exercise I am writing a small matrix library. I have a bunch more code, but I'll just show the part that's relevant to this question.

``````type
Matrix*[T; nrows, ncols: static[int]] = array[0 .. (nrows * ncols - 1), T]

# Get the index in the flattened array corresponding
# to row r and column c in the matrix
proc index(mat: Matrix, r, c: int): int =
result = r * mat.ncols + c

# Return the element at r, c
proc `[]`(mat: Matrix, r, c: int): Matrix.T =
result = mat[mat.index(r, c)]

# Set the element at r, c
proc `[]=`(mat: var Matrix, r, c: int, val: Matrix.T) =
mat[mat.index(r, c)] = val

# Add a value to every element in the matrix
proc `+=`(mat: var Matrix, val: Matrix.T) =
for i in 0 .. mat.high:
mat[i] += val

# Add a value to element at r, c
proc `[]+=`(mat: var Matrix, r, c: int, val: Matrix.T) =
mat[mat.index(r, c)] += val

# A test case
var mat: Matrix[float, 3, 4] # matrix with 3 rows and 4 columns
mat[1, 3] = 7.0
mat += 1.0

# add 8.0 to entry 1, 3 in matrix
`[]+=`(mat, 1, 3, 8.0) # works fine
``````

All this works fine, but I'd like to be able to replace the last line with something like

``````mat[1, 3] += 4.0
``````

This won't work (wasn't expecting it to either). If I try it, I get

``````Error: for a 'var' type a variable needs to be passed
``````

How would I create an addition assignment operator that has this behavior? I'm guessing I need something other than a proc to accomplish this.

6

Есть два способа сделать это:

• Перегрузка `[]`для `var Matrix`и возвращать `var T`(Это требует текущего Devel ветвь Nim):

``````proc `[]`(mat: Matrix, r, c: int): Matrix.T =
result = mat[mat.index(r, c)]

proc `[]`(mat: var Matrix, r, c: int): var Matrix.T =
result = mat[mat.index(r, c)]
``````
• Сделайте `[]`шаблон вместо:

``````template `[]`(mat: Matrix, r, c: int): expr =
mat[mat.index(r, c)]
``````

Это вызывает проблемы , когда `mat`не является ценностью, а что - то более сложное:

``````proc x: Matrix[float, 2, 2] =
echo "x()"

var y = x()[1, 0]
``````

Это печатает `x()`дважды.