给出以(* 3 (+ x y))
形式的表达式,如何评估表达式以便将其置于(+ (* 3 x) (* 3 y))
形式? (注意:在一般情况下,3是任何常量,“x”或“y”可以是单个变量或其他s表达式的术语(例如(+ 2 x)
)。
如何编写一个lambda表达式,它将递归计算原始表达式中的项(atoms?)并确定它们是常量还是术语?在术语的情况下,然后需要再次递归地评估它以确定该术语列表中每个项目的类型。
同样,问题的关键在于定义的递归“内核”。
我显然需要一个基本案例,一旦我到达表达式最深部分的最后一个单个原子就会确定。然后递归地“备份”工作,根据规则以适当的形式构建表达式。
来自Java / C ++背景我很难理解如何在Scheme中语法化。
答案 0 :(得分:4)
让我们快速绕开原始问题,略微相关。假设您获得以下内容:您希望编写一个评估程序,其中包含“{1}}之类的”字符串构建“表达式,并将其”评估“为”hellohellohello“。我们想要做的其他例子包括
之类的东西(* 3 "hello")
要解决这样的问题,我们需要准确指定输入的形状。基本上,我们想要描述一种数据类型。我们会说我们的输入将是“字符串表达式”。我们简称为(+ "rock" (+ (* 5 "p") "aper")) ==> "rockpppppaper"
(* 3 (+ "scis" "sors")) ==> "scissorsscissorsscissors"
。然后让我们定义str-exprs
的含义。
str-expr
是:
str-expr
<string>
(+ <str-expr> <str-expr>)
通过这种表示法,我们试图说(* <number> <str-expr>)
将适合这三种形状中的一种。
一旦我们对数据的形状有了很好的了解,我们就可以更好地编写处理str-expr
的函数的指南:他们必须对这三种选择进行案例分析!
str-exprs
其中'...'是我们要填写的内容。
实际上,我们知道如何更多地填写'...':我们知道在第二和第三种情况下,内部部分本身就是str-exprs。这些都是可能发生复发的主要地点:由于我们的数据是以其自身的形式描述的,因此处理这些数据的程序也可能需要参考自己。简而言之,处理;; A str-expr is either:
;; a plain string, or
;; (+ str-expr str-expr), or
;; (* number str-expr)
;; We want to write a definition to "evaluate" such string-expressions.
;; evaluate: str-expr -> string
(define (evaluate expr)
(cond
[(string? expr)
...]
[(eq? (first expr) '+)
...]
[(eq? (first expr) '*)
...]))
的程序几乎肯定会遵循这种形式:
str-expr
这一切都没有做任何真正的工作:我们可以完全理解这部分,因为这就是数据的形状告诉我们的。填写'...'的剩余部分以使这一切都成功实际上并不是太糟糕,特别是当我们考虑我们已经制作的测试用例时。 (Code)
这种标准的数据分析/案例分析是您问题的核心,也是HTDP等课程的广泛涵盖范围。这不是Scheme或Racket特定的:您在Java中进行相同类型的数据分析,并且您在许多其他地方看到了相同类型的方法。在Java中,用于案例分析的低机制可能以不同的方式完成,可能采用动态调度,但核心思想完全相同。您需要描述数据。获得数据定义后,使用它来帮助您勾画出处理该数据所需的代码。使用测试用例来三角测量如何填充草图。
答案 1 :(得分:1)
你需要打破你的问题。我将首先遵循HtDP(www.htdp.org)方法。你有什么投入?你能准确指出吗?在这种情况下,这些输入将是自我指涉的。
然后,指定输出表单。事实上,你上面的文字对此有点模糊:我想我知道你的输出形式是什么样的,但我不完全确定。
接下来,编写一组测试。这些应该基于输入术语的结构;从最简单的开始,然后从那里开始工作。
一旦你有一套好的测试,实现这个功能应该非常简单。如果你遇到困难,我很乐意帮忙!