在Racket/Scheme中使用本地

Gre*_*orn 5 scheme racket

在练习12年1月18日HTDP,我一直在使用"本地"重新编写马克西功能.

;; maxi : non-empty-lon  ->  number
;; to determine the largest number on alon
(define (maxi alon)
  (cond
    [(empty? (rest alon)) (first alon)]
    [else (local ((define m (maxi (rest alon))))
            (cond
              [(> (first alon) m) (first alon)]
              [(> m (first (rest alon))) m]
              [else (first (rest alon))]))]))
Run Code Online (Sandbox Code Playgroud)

我不确定为什么我会在"现实生活"中这样做,因为看起来这本书的版本更短,更清晰,也可能更快.

(define (maxi alon)
  (cond
    [(empty? (rest alon)) (first alon)]
    [else (cond
        [(> (first alon) (maxi (rest alon))) (first alon)]
        [else (maxi (rest alon))])]))
Run Code Online (Sandbox Code Playgroud)

它是否意味着纯粹的教学运动?有经验的Schemer可以评论上面的代码吗?谢谢.

Adr*_*lli 4

就我个人而言,我认为这是一个很糟糕的例子local,我不相信你完全理解这个问题的重要性,所以我要做的是回顾你应该注意到的概念,然后回顾你的例子,最后给你一个更好的例子。

概念

首先,这里的本地概念(以及其他许多事情)是为了澄清代码片段的含义。

你的例子

让我们考虑一下你的例子,你定义了一个名为的局部常量m,它看起来是正确的。不过,由于这封信m没有重大意义,您的解决方案似乎不清楚。那么,我们如何解决您的解决方案呢?

我们需要给出一个能够清楚地识别所代表的m内容的名称。所以,我们首先直接考虑什么代表什么mm(maxi (rest alon))

简单(maxi (rest alon))来说就是找到最大数量(rest alon)

所以让我们重命名mfind-max

现在你的代码看起来像:

;; maxi : non-empty-lon  ->  number
;; to determine the largest number on alon
(define (maxi alon)
  (cond
    [(empty? (rest alon)) (first alon)]
    [else (local ((define find-max (maxi (rest alon))))
            (cond
              [(> (first alon) find-max) (first alon)]
              [(> find-max (first (rest alon))) find-max]
              [else (first (rest alon))]))]))
Run Code Online (Sandbox Code Playgroud)

替换mfind-max使得代码更加清晰!留给我们的经验法则是,给你的常量赋予有意义的名称。

我的例子

为了进一步阐明,让我们考虑一个函数,该函数消耗两个点并生成通过连接这两个点创建的线段的斜率。我们的第一个方法可能是:

;;where x1,y1 belong to point 1 and x2,y2 belong to point 2
(define (find-slope x1 y1 x2 y2)
  (sqrt (+ (sqr (- x2 x1))) (sqr (- y2 y1))))
Run Code Online (Sandbox Code Playgroud)

但我们可以更清楚地使用local

(define (find-slope x1 y1 x2 y2)
  (local
    [(define delta-x (- x2 x1))
     (define delta-y (- y2 y1))]
    (sqrt (+ (sqr delta-x)) (sqr delta-y))))
Run Code Online (Sandbox Code Playgroud)

请注意 delta 如何描述该函数在该部分执行的操作;找出 x 或 y 的变化。所以,我们在这里需要学习的是,虽然第一个解决方案可能使用较少的代码,但第二个解决方案描述了我们正在做的事情并且可以轻松阅读。这就是问题的全部想法,它可能看起来很愚蠢,但这是他们在学术环境中学习方案时倾向于强调的惯例。

至于第一个和第二个解决方案的效率,出于明显的原因,第二个解决方案肯定要快得多(在您查看 Racket 如何评估表达式之后),但这不是问题的主要目的。

希望这可以帮助