是否有替代#34;设置!"关于计划

时间:2018-02-13 23:58:22

标签: functional-programming scheme lisp racket counting

想知道是否有使用套装的替代方案!在计划/球拍。 处理作业,我们不允许使用set!

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

(set! count (+ count 1))

想知道我将如何更改它以便它不会使用set!

2 个答案:

答案 0 :(得分:1)

据推测,您不被允许使用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作为另一个参数传递。只是一个猜测。

答案 1 :(得分: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)

这几乎是Fortran的lisp语法。如何做到这一点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))

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