函数式编程中的有效矩阵

Effective matrix in functional programming

我是 C/C++ 程序员,我开始学习 Racket / 阅读 SICP。我对函数式编程中矩阵的有效表示有疑问。

  1. 函数式编程中最有效的矩阵表示是什么?老阵好阵?我问是因为 SICP 作者使用矩阵的列表列表。
  2. 这是一个现实世界的问题:在我们的生产代码中,我们有一个函数,它在每个步骤中将随机值设置为矩阵单元格。简化的代码如下所示:

// up to N random cells initialized with random values

// matrix is a current state of the game field

for (n = 0; n < Random(N); n++)
{
    matrix[Random(X)][Random(Y)] = Random(MAX);
}

这段代码简单有效。如何为大型不可变矩阵编写有效的函数式代码?可能吗?如果是,那又如何?

非常感谢您的回答!

正如 Óscar 所说,最传统的函数式编程方法是使用链表。然而,更直接(尽管有一些变化)的方法是使用向量。

但是,既然你提到你在 Racket 中这样做,你实际上可以使用 for/vector 来制作你的矩阵。您可以使用向量的向量,如:

(define my-matrix
  (for/vector ([i (in-range 3)])
    (for/vector ([j (in-range 3)])
      (random))))

生成一个 3x3 随机数向量。现在您可以使用 vector-ref 两次从中获取一个元素。

;; Evaluates to the middle most cell in the matrix
(vector-ref (vector-ref my-matrix 1) 1)

您可以采用的另一种方法是采用类似 C 的方法,对整个矩阵使用单个向量。这当然需要您为宽度存储一个额外的参数,但可以使事情变得更清晰。1 例如,您可以创建一个包含数字 1 到 9 的 3x3 矩阵:

(define matrix-width 3)
(define matrix
  (for/vector ([i (in-range 1 10)])
    i))

现在你只需要一个 vector-ref 就可以得到你的元素:

;; This also gets the middle most cell.
(vector-ref matrix (+ 1 (* 1 matrix-width)) ; => 5

当然,如果您想经常这样做,将其包装到一个数据结构中是有意义的:

(struct matrix (width data))
(define (make-matrix width height)
  (make-vector (* width height)))
(define (matrix-ref m i j)
  (vector-ref (matrix-data m) (+ i (* j (matrix-width m)))))
(define (matrix-set! m i j v)
   (vector-set! (matrix-data m) (+ i (* j (matrix-width m))) v))

当然,你可以走得更远,做更多的工作和一个小宏,你甚至可以添加 for/matrixin-matrix 作为循环结构,以及矩阵数学库.但在某些时候,您将有效地制作了带有类型球拍的 math/matrix 库。2

1当然这纯属主观,还要看你的程序。

2从技术上讲,它也适用于标准的、无类型的 Racket,但速度要慢得多。

SICP 的作者想要教授计算机科学,特别是函数式编程。感兴趣的不是在 GNU/MIT-Scheme 解释器中展示不同的工具。 40 年来,我一直热爱 SICP 作为灵感来源。 你应该使用向量!