如何创建Scheme定义来解析复合S-expression并放入普通形式

时间:2013-01-30 22:59:18

标签: scheme racket mit-scheme

给出以(* 3 (+ x y))形式的表达式,如何评估表达式以便将其置于(+ (* 3 x) (* 3 y))形式? (注意:在一般情况下,3是任何常量,“x”或“y”可以是单个变量或其他s表达式的术语(例如(+ 2 x))。

如何编写一个lambda表达式,它将递归计算原始表达式中的项(atoms?)并确定它们是常量还是术语?在术语的情况下,然后需要再次递归地评估它以确定该术语列表中每个项目的类型。

同样,问题的关键在于定义的递归“内核”。

我显然需要一个基本案例,一旦我到达表达式最深部分的最后一个单个原子就会确定。然后递归地“备份”工作,根据规则以适当的形式构建表达式。

来自Java / C ++背景我很难理解如何在Scheme中语法化。

2 个答案:

答案 0 :(得分:4)

让我们快速绕开原始问题,略微相关。假设您获得以下内容:您希望编写一个评估程序,其中包含“{1}}之类的”字符串构建“表达式,并将其”评估“为”hellohellohello“。我们想要做的其他例子包括

之类的东西
(* 3 "hello")

要解决这样的问题,我们需要准确指定输入的形状。基本上,我们想要描述一种数据类型。我们会说我们的输入将是“字符串表达式”。我们简称为(+ "rock" (+ (* 5 "p") "aper")) ==> "rockpppppaper" (* 3 (+ "scis" "sors")) ==> "scissorsscissorsscissors" 。然后让我们定义str-exprs的含义。

str-expr是:

  1. str-expr
  2. <string>
  3. (+ <str-expr> <str-expr>)
  4. 通过这种表示法,我们试图说(* <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)方法。你有什么投入?你能准确指出吗?在这种情况下,这些输入将是自我指涉的。

然后,指定输出表单。事实上,你上面的文字对此有点模糊:我想我知道你的输出形式是什么样的,但我不完全确定。

接下来,编写一组测试。这些应该基于输入术语的结构;从最简单的开始,然后从那里开始工作。

一旦你有一套好的测试,实现这个功能应该非常简单。如果你遇到困难,我很乐意帮忙!