球拍可变变量

时间:2012-12-16 04:23:39

标签: variables scheme racket mutable

我是新手,并且遇到了我需要一个可变数值变量的实例

下面是一个通过一串位(101011 ....)工作的函数,如果它遇到1改变一个名为“value”的数值变量,如果它遇到0必须改变同一个变量“value” 。因此,当我们到达字符串的末尾时,我们应该得到总数为“值”。

(define (implode bstr value)
        (for ([c (string-length bstr)])
           (display (string-ref bstr c))
      (if (eqv? (string-ref bstr c) #\1) (displayln (+ (/ value 3) 17))
          (displayln (/ value 3)))))

如果没有mtauble变量,我可以通过prgram运行这个变量吗?

3 个答案:

答案 0 :(得分:5)

正如已经提出的,使用递归可以很容易地解决这个问题,而不使用可变变量。这是在Scheme中编写过程的首选方法:

(define (implode bstr value)
  (let loop ((value value)
             (lst (string->list bstr)))
    (cond ((null? lst)
           value)
          ((char=? (car lst) #\1)
           (loop (+ (/ value 3) 17) (cdr lst)))
          ((char=? (car lst) #\0)
           (loop (/ value 3) (cdr lst)))
          (else (error "unexpected char" (car lst))))))

答案 1 :(得分:5)

球拍支持突变。例如:

#lang racket

;; count-whales: (listof string) -> number
;; Returns a count of the number of whales in lst.
(define (count-whales lst)
  (define c 0)
  (for ([thing lst])
    (when (equal? thing "shamu")
      (set! c (add1 c))))
  c)

;; Example:
(count-whales '("shamu" "donald duck" "shamu"))

你可能习惯于以这种方式看循环,其中变异允许我们记录一些运行值。用突变写作没有障碍。但话虽如此,上述功能并不是惯用的Racket。相反,Racketeer会使用一个可以累积值的循环,而不是使用变异。

以下是使用累加器编写时上述函数的样子:

#lang racket

;; count-whales: (listof string) -> number
;; Returns a count of the number of whales in lst.
(define (count-whales lst)
  (for/fold ([c 0])
            ([thing lst])
    (if (equal? thing "shamu")
        (add1 c)
        c)))

;; Example:
(count-whales '("shamu" "donald duck" "shamu"))

答案 2 :(得分:4)

我不确定implode函数的目标是什么,但是,您肯定不需要使用变异。 Racket是一种高级语言,具有尾调用消除功能,这意味着通过本地函数进行的循环就像Óscar的例子中所做的那样,编译器稍后会变成使用变异或任何需要的有效代码。

但更重要的是,展示如何编写更简洁且可能更接近突变心理模型的球拍代码将是一件好事。这里的主要成分是for/fold,它正在执行“for循环”,但在整个循环中使用“状态变量”。这里的“状态”是引用的,因为它并不存在 - 它实际上是一个宏,它扩展到类似于Óscar的例子中的循环。我还以一些次要但有用的方式改进了代码的其他部分:你可以直接遍历字符串,不需要索引;那里并不真正需要in-string,但它会使迭代类型更加明确,使其更快,并且如果bstr不是字符串,则会抛出错误;您可以使用case来检查您所在的角色;只要你使用它,如果一个字符既不是“0”也不是“1”,最好抛出一个错误。

以下是它的样子:

(define (implode bstr)
  (for/fold ([value 0]) ([c (in-string bstr)])
    (case c
      [(#\0) (+ (/ value 3) 17)]
      [(#\1) (/ value 3)]
      [else (error 'implode "bad character: ~e" c)])))

但是,这会产生一些奇怪的结果,但同样,我不确定这个函数应该做什么......