访问并更改使用`define`创建的值

时间:2010-12-30 11:50:18

标签: scheme racket

我正在制作游戏,我有这个:

(define b "black piece") (define w "white piece")

(define (board)
 (lambda (matrix) 
   (list ((b w b w b w b w) 
          (w b w b w b w b) 
          (b w b w b w b w) 
          (w b w b w b w b) 
          (b w b w b w b w) 
          (w b w b w b w b) 
          (b w b w b w b w) 
          (w b w b w b w b)))))

board列出了8行和8列黑白作品。

如何访问和更改电路板的元素?如何使用递归来执行过程矩阵?

1 个答案:

答案 0 :(得分:0)

首先注意几点:
(define f (lambda (x) l ))
与。相同 (define (f x) l ))
然而,你将它们与
结合起来 (define (board) (lambda (matrix) l ))
这与
相同 (define board (lambda () (lambda (matrix) l )))

区别很重要。前两个我已经将bind f列为一个函数,该函数接受一个参数并返回l。我猜这就是你想要做的。在接下来的两个中,你将板绑定到一个不带参数的函数,并返回一个带有1个参数矩阵的函数(它似乎没有做任何事情),并返回一个l。

第二个问题,(list ((b w....) ...))无效,因为它会尝试评估(b w ...)。您需要在电路板的每一行的函数应用程序位置都有列表,如(list (list b w ...) (list w b ...) ...),以便您编码甚至编译。

关于你的问题。 link-ref包含在racket / base中,当您知道列表中的索引时,它用于引用列表中的元素。
(list-ref 2(列出'a'b'c'd))
将返回'c。索引从0开始。由于您有一个列表列表,您需要两次应用list-ref来检索'b或'w。

至于改变它,你不能。从r6rs开始,对(组成列表)是不可变的。在可能的情况下,建议的做法是返回包含更改的新列表。你可以使用这个效率低下的list-set版本,它会在索引处返回一个带有新值的列表副本。

(define (list-set lis idx val)
  (map (lambda (e i)
    (if (= i idx) val e))  
    lis  
    (iota (length lis))))

但是,在这种情况下,我建议切换到更适合手头任务的不同数据结构,因为您可能希望O(1)访问板中的元素。查看vectors,其行为与列表非常相似,但用于持续查找和更新。有一个内置的vector-refvector-set!操作,您应该使用它而不是我的上述功能。

如果这是一个较大问题的一部分,并且您已经在任何地方使用列表,则可以使用vector->listlist->vector函数来回转换。此外,您可以使用mutable lists但不能使用。

更好的是srfi/25中提供的多维数组库,但这可能会更复杂。

问题的第二部分是如何递归地构建电路板。好吧,这是一个使用map的版本。

(require (lib "1.ss" "srfi"))
(define (board)
  (map (lambda (x)
         (map (lambda (y)
                (if (odd? (+ x y)) b w))
              (iota 8)))
       (iota 8)))

这是一个递归版本

(define (board)
  (letrec ((board-helper
            (lambda (x)
          (if (eq? x 8) '()
          (cons (row-helper x 0) (board-helper (+ 1 x))))))
       (row-helper
        (lambda (x y)
          (if (eq? y 8) '()
          (cons (if (odd? (+ x y)) b w) (row-helper x (+ 1 y)))))))
    (board-helper 0)))