Nim statement overload

Just started programming in Nim (which I really like so far). As a training exercise, I am writing a small matrix library. I have even more code, but I will just show the part related 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 

It all works great, but I would like to be able to replace the last line with something like

 mat[1, 3] += 4.0 

This will not work (this was not expected). If I try, I get

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

How to create an assignment operator that has this behavior? I assume that for this I need something other than proc.

+5
source share
1 answer

There are two ways to do this:

  • Overloading [] for var Matrix and returning var T (this requires the current Nim division branch):

     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)] 
  • Make a template instead of [] :

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

    This causes a problem when mat not a value, but something more complex:

     proc x: Matrix[float, 2, 2] = echo "x()" var y = x()[1, 0] 

    This prints x() twice.

+6
source

All Articles