【问题标题】:Racket mutable variables球拍可变变量
【发布时间】:2012-12-16 04:23:38
【问题描述】:

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

下面是一个通过一串位(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 运行时更改此变量?

【问题讨论】:

  • 谁说你需要可变性?提示:您可以递归地而不是迭代地执行此操作。
  • 好吧,我是游戏,你能举个例子吗?

标签: variables scheme racket mutable


【解决方案1】:

Racket 支持突变。例如:

#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"))

您可能习惯于以这种方式查看循环,其中变异允许我们记录一些运行值。使用突变进行写作没有障碍。但话虽如此,上述功能并不是惯用的球拍。 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】:

    正如已经建议的那样,这个问题可以很容易地使用递归来解决,而无需使用可变变量。这是在 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))))))
    

    【讨论】:

    • 非凡 - 它运作良好 - 谢谢,现在弄清楚你做了什么
    • @user1907316 很高兴听到这个消息!如果此答案对您有帮助,请不要忘记点击左侧的复选标记接受它
    【解决方案3】:

    我不确定implode 函数的目标是什么,但是是的,您绝对不需要使用突变。 Racket 是一种高级语言,它具有尾调用消除功能,这意味着通过 Óscar 示例中所做的本地函数循环是编译器稍后将转换为使用突变或任何需要的有效代码的东西。

    但除此之外,最好展示如何编写更简洁的 Racket 代码,并且可能更接近突变的心理模型。这里的主要成分是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)])))
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-28
      • 1970-01-01
      • 1970-01-01
      • 2022-12-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多