【问题标题】:Is there an alternative for "set!" on Scheme“设置!”有替代方案吗?关于方案
【发布时间】:2018-07-24 11:03:29
【问题描述】:

想知道是否有使用 set 的替代方法!在计划/球拍中。 处理作业,我们不能使用 set!

对于我的一个功能,我有一个增量器

(set! count (+ count 1))

想知道如何更改它以使其不使用 set!

【问题讨论】:

  • 如果你的“函数”保持内部状态,那么它不是一个函数,而是一个过程:一个函数是定义的,这样(f x) 只依赖于x。可能目的是让您学习编写功能性程序。
  • 几乎总是,替代方法是递归 - 特别是当周围有列表时。免费书籍:SICPHtDP.

标签: functional-programming scheme lisp racket counting


【解决方案1】:

set! 永远不需要。想象一下你有这个程序:

(define (count lst)
  (define num 0)
  (define (helper lst)
    (when (not (null? lst))
      (set! num (+ num 1))
      (helper (cdr lst))))
  (helper lst)
  num)

这几乎是带有 lisp 语法的 Fortran。如果没有set!,这将如何完成。一种方法是使用盒子:

(define (count lst)
  (define num (list 0))
  (define (helper lst)
    (when (not (null? lst))
      (set-car! num (+ (car num) 1))
      (helper (cdr lst))))
  (helper lst)
  (car num))

正如 SICP 视频中所解释的,当您引入一种突变时,您可以使用它来执行所有类型的突变。作为琐事,这是一个通常由 Scheme 编译器完成的转换,因此在许多情况下,实现基础语言具有 set-car! 而不是 set!。没有突变怎么办?诀窍是隐藏绑定:

(define (count lst)
  (define (helper num lst)
    (if (not (null? lst))
        (helper (+ num 1) (cdr lst))
        num))
  (helper 0 lst))

这实际上变得更简单了。想象一下,您只需要更新一些变量,然后您只需在其他地方使用相同的变量进行递归。

【讨论】:

    【解决方案2】:

    大概,不允许您使用set! 的原因是您被要求以功能性方式解决问题,而不是命令式方式。让我用两个不同的函数来说明,它们都决定了列表的长度:

    #lang racket
    
    (require rackunit)
    
    (define count 0)
    (define (imperative-length l)
      (cond [(empty? l) count]
            [else (set! count (+ 1 count))
                  (imperative-length (rest l))]))
    
    (check-equal? (imperative-length '(4 3 2 1)) 4)
    
    
    (define (functional-length l)
      (cond [(empty? l) 0]
            [else (+ 1 (functional-length (rest l)))]))
    
    
    (check-equal? (functional-length '(4 3 2 1)) 4)
    
    
    ;; what happens if we try calling imperative-length again?
    
    
    (check-equal? (imperative-length '(4 3 2 1)) 4)
    
    ;; oh no!
    
    ;; what happens if we try calling functional-length again?
    
    (check-equal? (functional-length '(4 3 2 1)) 4)
    
    ;; yep, works fine.
    

    这两个函数都可以正常工作,但是可以重复调用函数函数。但!但!你可能会说,我只需要记住将计数器设置为零,或者将count 的绑定放在函数内部。确实如此,但一般来说,函数式解决方案根本不需要程序员担心这种交互。

    那么,这对您意味着什么?这可能意味着您需要将count 作为另一个参数传递。只是猜测。

    【讨论】:

    • 我们也可以说 no 可以替代set!,其中set! 是完成这项工作的唯一方法(即在闭包中改变隐藏的绑定,使用通信对象或其他东西的网络)。 :)
    猜你喜欢
    • 2012-05-29
    • 2021-12-03
    • 2019-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-16
    相关资源
    最近更新 更多