在球拍/方案中使用本地
在 htdp 的练习 18.1.12 中,我使用“local”重写了 maxi 函数。
;; 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))]))]))
我不确定为什么我会在“现实生活”中这样做,因为这本书的版本似乎更短、更清晰,而且可能也更快。
(define (maxi alon)
(cond
[(empty? (rest alon)) (first alon)]
[else (cond
[(> (first alon) (maxi (rest alon))) (first alon)]
[else (maxi (rest alon))])]))
这是纯粹的教学练习吗?有经验的Schemer可以评论一下上面的代码吗?谢谢。
In Exercise 18.1.12 from htdp, I've re-written the maxi function using "local".
;; 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))]))]))
I'm not sure why I would do this in "real life" as it seems the book's version is shorter, clearer and probably faster as well.
(define (maxi alon)
(cond
[(empty? (rest alon)) (first alon)]
[else (cond
[(> (first alon) (maxi (rest alon))) (first alon)]
[else (maxi (rest alon))])]))
Was it meant to be a purely pedagogical exercise? Could an experienced Schemer comment on the code above? Thank you.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
就我个人而言,我认为这是一个很糟糕的例子来说明本地的重要性,并且我不相信您完全理解这个问题的重要性,所以我要做的是回顾一下您应该注意到的概念,然后检查你的例子,最后给你一个更好的例子。
概念
首先,这里的本地概念(以及许多其他事物)是为了澄清代码片段的含义。
您的示例
让我们考虑一下您的示例,您定义了一个名为
m
的局部常量,该常量似乎是正确的。尽管如此,由于字母m
没有重要意义,因此您的解决方案似乎不清楚。那么,我们如何解决您的解决方案呢?我们需要给
m
一个能够清楚识别m
所代表内容的名称。因此,我们首先直接考虑m
代表什么,即(maxi (rest alon))
那么
(maxi (rest alon))
简单地说找到(rest alon)
的最大数量所以让我们将
m
重命名为find-max
现在你的代码看起来像:
替换
m< /code> 加上
find-max
使代码更加清晰!留给我们一个经验法则,为您的常量指定有意义的名称。我的示例
为了进一步阐明,让我们考虑一个函数,该函数消耗两个点并生成通过连接这两个点创建的线段的斜率。我们的第一个方法可能是:
但是使用
local
可以更清楚:注意 delta 如何描述函数在该部分的作用;找出 x 或 y 的变化。因此,我们在这里需要了解的是,虽然第一个解决方案可能使用较少的代码,但第二个解决方案描述我们正在做的事情并且可以轻松阅读。这就是问题的全部想法,它可能看起来很愚蠢,但这是他们在学术环境中学习方案时倾向于强调的惯例。
至于第一个和第二个解决方案的效率,出于明显的原因,第二个解决方案肯定要快得多(在您查看 Racket 如何计算表达式之后),但这不是问题的主要目的。
希望这有帮助
Personally, I think this is a poor example of the importance of
local
and I don't believe you fully understood the importance of the question, so what I will do is go through the concept that you should notice, then go through your example and finally give you a better example.CONCEPT
First off, the idea of local here (among many other things) is to clarify the meaning of snippets of code.
YOUR EXAMPLE
Lets consider your example, you define a local constant called
m
which appears to be correct. Although, since the letterm
has no significant meaning your solution appears to be unclear. So, how might we fix your solution?We need to give
m
a name that clearly identifies whatm
represents. So, we begin by directly considering whatm
represents which is(maxi (rest alon))
Well
(maxi (rest alon))
simply says find the maximum number of(rest alon)
So lets rename
m
tofind-max
Now your code looks like:
Replacing
m
withfind-max
makes the code much clearer! Leaving us with a rule of thumb, give your constants meaningful names.MY EXAMPLE
To further clarify, lets consider a function that consumes two points and produces the slope of the line segment created by connecting the two points. Our first approach might be:
But we could be clearer using
local
:Notice how delta describes what the function does at that part; finding the change in x or y. So, what we need to learn here is that, although the first solution may make use of less code, the second solution describes what we are doing and can be easily read. That was the entire idea of the question and it may seem stupid, but it is a convention they tend to stress when learning scheme in an academic setting.
As for the efficiency of the first and second solution, the second solution is definitely much faster for obvious reasons (after you look at how Racket evaluates expressions), but that wasn't the main purpose of the question.
Hope this helps
除了使用
local
之外,还可以使用 Racket 的内部定义(尤其是更新的版本)。例如:
Instead of using
local
, one can go as well using Racket's internal definitions (especially with more recent versions).For example:
使用 local 在这里速度更快,因为它每次递归只计算一次
(maxi (rest alon))
,而在第二个版本中,它计算(maxi (rest alon))
两次每当到达最后一种情况时:本地都会保存结果,这样您就不会重复执行相同的工作。请注意,如果您将
(maxi (rest alon))
与 local 一起取出,则不再是 else 情况:Using local is way faster here because it only evaluates
(maxi (rest alon))
once per recursion, whereas with the second version it evaluates(maxi (rest alon))
twice whenever it gets to the last case:Local saves the result so you don't do the same work twice. Notice if you lift the
(maxi (rest alon))
out with local, it isn't in the else case anymore: