快速业务通道

面向Java开发人员的Scala指南 - 构建计算器,第3部分 - 编程入门网

作者 佚名技术 来源 NET编程 浏览 发布时间 2012-06-20
011-01-30 Ted Neward

读者可以再增加一些测试,因为我可能漏掉一些不常见的情况(与 Internet 上的其他人结对编程是比较好的)。

完成最后一步

假设解析器正按照我们想要的方式在工作 — 即生成 AST — 那么现在只需要根据 AST 对象的计算结果来完善解析器。这很简单,只需向 Calc 添加代码,如清单 8 所示……

清单 8. 真的完成啦!

package com.tedneward.calcdsl {   // ...   object Calc   {    // ...    def evaluate(text : String) : Double = evaluate(parse(text))   } }

……同时添加一个简单的测试,确保 evaluate("1+1") 返回 2.0……

清单 9. 最后,看一下 1 + 1 是否等于 2

package com.tedneward.calcdsl.test {   class CalcTest   {    import org.junit._, Assert._    // ...    @Test def add1 =     assertEquals(Calc.evaluae("1 + 1"), 2.0)   } }

……然后运行它,一切正常!

扩展 DSL 语言

如果完全用 Java 代码编写同一个计算器 DSL,而没有碰到我遇到的问题(在不构建完整的 AST 的情况下递归式地计算每一个片段,等等),那么似乎它是另一种能够解决问题的语言或工具。但以这种方式构建语言的强大之处会在扩展性上得到体现。

例如,我们向这种语言添加一个新的运算符,即 ^ 运算符,它将执行求幂运算;也就是说,2 ^ 2 等于 2 的平方 或 4。向 DSL 语言添加这个运算符需要一些简单步骤。

首先,您必须考虑是否需要更改 AST。在本例中,求幂运算符是另一种形式的二进制运算符,所以使用现有 BinaryOp case 类就可以。无需对 AST 进行任何更改。

其次,必须修改 evaluate 函数,以使用 BinaryOp("^", x, y) 执行正确的操作;这很简单,只需添加一个嵌套函数(因为不必在外部看到这个函数)来实际计算指数,然后向模式匹配添加必要的代码行,如下所示:

面向Java开发人员的Scala指南 - 构建计算器,第3部分(6)

时间:2011-01-30 Ted Neward

清单 10. 稍等片刻

package com.tedneward.calcdsl {   // ...   object Calc   {    // ...    def evaluate(e : Expr) : Double =    {     def exponentiate(base : Double, exponent : Double) : Double =      if (exponent == 0)       1.0      else       base * exponentiate(base, exponent - 1)     simplify(e) match {      case Number(x) => x      case UnaryOp("-", x) => -(evaluate(x))      case BinaryOp("+", x1, x2) => (evaluate(x1) + evaluate(x2))      case BinaryOp("-", x1, x2) => (evaluate(x1) - evaluate(x2))      case BinaryOp("*", x1, x2) => (evaluate(x1) * evaluate(x2))      case BinaryOp("/", x1, x2) => (evaluate(x1) / evaluate(x2))      case BinaryOp("^", x1, x2) => exponentiate(evaluate(x1), evaluate(x2))     }    }   } }

注意,这里我们只使用 6 行代码就有效地向系统添加了求幂运算,同时没有对 Calc 类进行任何表面更改。这就是封装!

(在我努力创建最简单求幂函数时,我故意创建了一个有严重 bug 的版本 —— 这是为了让我们关注语言,而不是实现。也就是说,看看哪位读者能够找到 bug。他可以编写发现 bug 的单元测试,然后提供一个无 bug 的版本)。

但是在向解析器添加这个求幂函数之前,让我们先测试这段代码,以确保求幂部分能正常工作:

清单 11. 求平方

package co

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号