scala适合开发什么,Scala语言的主要应用领域与作用?
scala适合开发什么,Scala语言的主要应用领域与作用?详细介绍
本文目录一览: 编程语言Scala一般用于做什么样的项目
用在数据处理的工具比较多。功能编程比迭代程序开销少,更适合云平台计算。
用在数据处理的工具比较多。功能编程比迭代程序开销少,更适合云平台计算。
Scala有交互式命令行(REPL), 可以在上面快速的试各种语法和代码。这对学习新特性,或者实验新想法非常有用。(第1章)
一致性: 尽管Scala融合了静态类型系统、面向对象、函数式编程等语言特性,但却很少能看出融合的痕迹。Scala是我见到融合最多语言特性而又不显得杂乱的编程语言之一。
类型安全:Scala创始人是教授,他先带领创建了Java 5编译器,而后觉得Java有太多羁绊而发明了Scala。 Scala编译器和类型系统非常强大,它的目标是尽量把软件错误消灭在编写过程中。 Scala类型系统是图灵完备的,甚至可以在编译期间解决问题。
面向对象: Scala是面向对象的编程语言,所有的变量和方法都封装在对象中,可以把信息封装起来供外部使用。(第2章)
函数式编程:Scala同时又是函数式编程语言,函数可以独立存在,可以定义一个函数作为另一个函数的返回值,也可以接受函数作为函数的参数。这给组合函数带来了很大的便利。如何把面向对象编程形容成搭积木的话,函数式编程就像拼线条,更灵活和更有创意。(第3章)
异步编程: 由于函数式编程提倡变量不可变,使异步编程变得非常容易。同时Scala提供的Future(第5章), 和akka类库(第9-11章),使得异步编程变得非常容易。
基于JVM: Scala会被编译成为jvm bytecode,所以Scala能无缝集成已有的Java类库。你可以非常自然的使用已经存在的非常庞大且稳定的Java类库,比如小巧好用的apache.common.*, 或者Java上的各种工具类库。
因为如此众多特性,用Scala可以优雅地编写简洁的代码,同时又能减少很多低级错误;能快速进行开发,又能保证系统性能、团队协作和长期维护。
Scala语言的主要应用领域与作用?
Scala的特性
1.面向对象特性
Scala是一种纯面向对象的语言,每一个值都是对象。对象的数据类型以及行为由类和特征(Trait)描述。类抽象机制的扩展有两种途径。一种途径是子类继承,另一种途径是灵活的混入(Mixin)机制。这两种途径能避免多重继承的种种问题。
2.函数式编程
Scala也是一种函数式语言,其函数也能当成值来使用。Scala提供了轻量级的语法用以定义匿名函数,支持高阶函数,允许嵌套多层函数,并支持柯里化。Scala的CaseClass及其内置的模式匹配相当于函数式编程语言中常用的代数类型(AlgebraicType)。
更进一步,程序员可以利用Scala的模式匹配,编写类似正则表达式的代码处理XML数据。在这些情形中,顺序容器的推导式(comprehension)功能对编写公式化查询非常有用。
由于JVM不支持尾部递归,Scala也不能完全支持尾部递归优化。不过,在简单的情况下,Scala编译器可以把尾部递归优化成循环。
4.静态类型
Scala是具备类型系统,通过编译时的检查,保证代码的安全性和一致性。类型系统具体支持以下特性:
泛型类,型变注释(VarianceAnnotation),类型继承结构的上限和下限,把类别和抽象类型作为对象成员,复合类型,引用自己时显式指定类型,视图,多态方法。
5.扩展性
Scala的设计承认一个事实,即在实践中,某个领域特定的应用程序开发往往需要特定于该领域的语言扩展。Scala提供了许多独特的语言机制,可以以库的形式轻易无缝添加新的语言结构:
任何方法可用作前缀或后缀操作符,可以根据预期类型自动构造闭包。联合使用以上两个特性,使你可以定义新的语句而无须扩展语法也无须使用宏之类的元编程特性。
5.使用Scala的框架
Lift是一个开源的Web应用框架,旨在提供类似RubyonRails的东西。因为Lift使用了Scala,所以Lift应用程序可以使用所有的Java库和Web容器。
scala语言主要应用领域
cala运行于JVM之上,并且它可以访问任何的java类库并且与java框架进行互操作,scala也大量重用了java类型和类库。
大数据的开发语言是Scala的原因:
1:大数据的本身是计算数据,而Scala即有面向对象组织项目工程的能力,又有计算数据的功能。
2:现在大数据事实上的计算标准框架Spark,它是用Scala开发的,因为计算数据,Scala它是函数式编程,它实现算法非常简洁优雅。
例:kafka,它是一个消息中间件,如果外部数据要流进大数据中心,我们一般都要用kafka作适配器,那如果大数据中心的数据流到外部,也是用kafka(如Spark计算的数据要交给HBASE或MySql,期间我们都会用kafka),很多的大数据组件都是用的Scala编写的,所以,如果你想成为一个较高级的大数据开发高手,你一定要掌握Scala。
Scala 是一门怎样的语言,具有哪些优势
曾经有人问Java的创始人高斯林这样一个问题,“除了Java语言以外,您现在还使用JVM平台上的哪种编程语言?”他毫不犹豫的说是Scala。
Scala到底是什么?在目前众多的JVM语言当中,Scala无疑是最引人注意的语言之一。Scala是一个静态语言,更适合大型工程项目,Scala直接编译成Java字节码,性能接近Java。Scala是一个多范式的语言,你可以混合使用函数式和面向对象编程,混合使用可变类和不变类,混合使用Actor和传统的Java并发库。
短短一个月的时间,Scala于本月冲进了TIOBE的前五十名。一个 Twitter 的开发人员说过,Scala 将会成为现代 Web2.0 的发起语言。LinkedIn 也用这种语言。同样许多其他大的公司如 Sony Picture, EDF, SAP 也开始使用这种语言。为什么Scala发展这么迅猛,可以获得如此热烈的社区支持。
曾冠东还表示,Scala不是Java的杀手,它无法取代Java的地位,也突破不了JVM的限制、Java实现不了的功能它也实现不了。我们可以将Scala形象的理解成大量语法糖的Java。
Scala 开发团队发布了最新的2.9.2稳定版本,Scala 语言的特性有许多,例如高阶函数和对象、抽象类型绑定,actor 使得函数在 Scala 中能是一个子类成为可能,Scala 中的设计模式使得面向对象和函数编程无缝结合。Akka 是一个用 Scala 编写的库,用于简化编写容错的、高可伸缩性的 Java 和 Scala 的 Actor 模型应用。它已经成功运用在电信行业。Spark 是一种可扩展的数据分析平台,它整合了内存计算的基元,因此,相对于 Hadoop 的集群存储方法,它在性能方面更具优势。Spark 是在 Scala 语言中实现的,并且利用了该语言,为数据处理提供了独一无二的环境。Scala 编译器可以生成字节码,直接运行在使用JVM上。该语言(它实际上代表了可扩展语言)被定义为可直接集成到语言中的简单扩展。
Scala作为一门静态语言,它的主要特性有哪些?
· Scala是面向对象的
Scala是一个纯面向对象语言,在某种意义上来讲所有数值都是对象。对象的类型和行为是由class和trait来描述的。Class的抽象可由子类化和一种灵活的基于mixin的组合机制(它可作为多重继承的简单替代方案)来扩展。
· Scala是函数式的
Scala还是一个函数式语言,在某种意义上来讲所有函数都是数值。Scala为定义匿名函数提供了一种轻量级的语法,它支持高阶(higher-order)函数、允许函数嵌套、支持局部套用(currying)。Scala的case类及其内置支持的模式匹配模型代数类型在许多函数式编程语言中都被使用。
· Scala是静态类型的
Scala配备了一套富有表现力的类型系统,该抽象概念以一种安全的和一致的方式被使用。
· Scala是可扩展的
Scala的设计承认了实践事实,领域特定应用开发通常需要领域特定语言扩展。Scala提供了一个独特的语言组合机制,这可以更加容易地以类库的形式增加新的语言结构:
任何方式可以被用作中缀(infix)或后缀(postfix)操作符闭包按照所期望的类型(目标类型)自动地被构造
两者结合使用可方便地定义新语句,无需扩展语法,也无需使用类似宏的元编程工具。
· Scala可与Java和.NET进行互操作
Scala设计时就考虑了与流行编程环境良好交互,如Java 2运行时环境(JRE)和 .NET框架(CLR)。特别是与主流面向对象语言,如Java和C#尽量无缝交互。Scala有像Java和C#一样的编译模型(独立编译,动态装载类),允许访问成千上万的高质量类库。
在并发性方面,与 Scala 在 .NET 领域中的姐妹语言 F# 相似,Scala 是针对 “并发性问题” 的解决方案之一,让开发人员能够更加轻松地专注于问题的实质,而不用考虑并发编程的低级细节。Actor 编程模式让高度并行应用程序的开发更加简单。Scala把Erlang风格的基于actor的并发带进了JVM。我们可以利用Scala的actor模型在JVM上设计具伸缩性的并发应用程序,以自动获得多核心处理器带来的优势,而不必依照复杂的Java线程模型来编写程序。Scala 为并发性提供了两种级别的支持,这与其他与 Java 相关的主题极为类似:
首先,对底层库的完全访问(比如说 java.util.concurrent)以及对 “传统” Java 并发性语义的支持(比如说监控程序和wait()/notifyAll())。其次,这些基本机制上面有一个抽象层
Scala 提供了在稳定的高性能平台(Java 虚拟机)上生成的能力同时也是一门敏捷性语言。这一类型的语言也有其他的选择,例如 Jython, JRuby, Groovy 和 Clojure, 但是这些都是运行在 JVM 上的动态类型语言。Open Class 的效果让大家会觉得Scala是动态语言,但它是选择隐式转换来实现的,这也正好证明了Scala是静态语言。隐式转换(Implicit conversion)使 Scala 具有类型安全性,正如扩展方法(extension method)之于 C#,开放类(open class)之于 ruby。即:向未曾定义的类型添加方法(如字符串、列表、整数)。这是使得 Scala 符合 DSL(特定领域语言)模型的特性之一。
Scala结合了面向对象和函数编程的优势,函数编程的一个好处就是你能够像运用一个数据那样运用函数,可以用来定义真正高层级的库,或者去定义新的领域特殊语言(DSL)。
在谈及Java与Scala的对比时,曾冠东表示,Scala能调用绝大部分的Java,而Java调用Scala独有的东西会比较难。Java 拥有非常强的概念规范,因此任何一个 Java 程序之间具有非常多的相似之处,并且这样能够方便的进行程序员交替。但是 Scala 并没有这样的统一性,因为这是一门很有表现力的语言。现场曾冠东为我们演示了实际案例,如下图所示:
正所谓,金无足赤,人无完人。Scala对二进制不兼容,语法也越来越复杂,不能突破Bytecode的限制、编译速度有所缓慢。当它被广泛用于单元测试、开发工具、Socket开发、以及面对多核挑战的并发应用。总而言之,Scala是一种函数式面向对象语言,它融汇了许多前所未有的特性,而同时又运行于JVM之上。正如JRuby 创建者之一Charles Nutter 所宣称的那样Scala就是 Java 王位的合法继承人。随着开发者对Scala的兴趣日增,以及越来越多的工具支持,无疑Scala语言将成为广大软件工程师手上一件必不可少的工具。更多精彩内容,请关注专题:http://www.it168.com/remen/qcon/
Scala在大数据处理方面有何优势?
Scala是不善于处理大数据的。作为一个函数式语言,必须在内存消耗和性能消耗两者之间徘徊,而普通的命令式语言就并不会有这种问题。举个例子,从数据结构来看,函数式语言要求不能修改原有结构(如果修改了,就不再吻合Immutable这一黄金定律),对于普通的链表(链表List在函数式语言中比数组Array更常见),每当你做一次操作,比如增加元素,删减元素等等,照理说会生成一个新的链表,而非像过程式语言,直接通过指针对链表本身进行修改。为了让操作速度达到与过程式语言类似或者相匹配,函数式语言的天才们发明了很多种不同方法,比如用结构分享(Structural Sharing)的技巧来应付链表,每次操作只记录下那一项特殊操作,而不毁坏或者替代原有链表。对更高级一些的结构,比如哈希图(HashMap),普通命令式语言用哈希列表(HashTable)这种简单的方式来执行,但悲壮的函数式语言就必须依赖于2-3拇指树(2-3 Finger Trie)一类的高端结构来达到相同的操作效率。
我想大部分应用开发程序员,最关键是看有什么类库合适的方便特定领域的应用开发。就像ruby有rails做web开发,你可以去论证ruby优缺点,但实际上应用开发效率提升很大程度上依靠类库。现在Spark是大数据领域的杀手级应用框架,BAT,我们现在几个领域巨头的客户(有保密协议不方便透露)都全面使用Spark了,这个时候再谈Scala适不适合大数据开发其实意义不大。因为大家比的不只是编程语言,而是构建在这个编程语言之上的类库、社区和生态圈(包括文档和数据、衍生类库、商业技术支持、成熟产品等等)。那么反过来问,为什么Spark会选择Scala可能更有意义一点。Spark主创Matei在不同场合回答两次这个问题,思考的点稍微不一样,但重点是一样的,很适合回答题主的问题。
总结来说最主要有三点:1.API能做得优雅;这是框架设计师第一个要考虑的问题,框架的用户是应用开发程序员,API是否优雅直接影响用户体验。2.能融合到Hadoop生态圈,要用JVM语言;Hadoop现在是大数据事实标准,Spark并不是要取代Hadoop,而是要完善Hadoop生态。JVM语言大部分可能会想到Java,但Java做出来的API太丑,或者想实现一个优雅的API太费劲。3.速度要快;Scala是静态编译的,所以和JRuby,Groovy比起来速度会快很多,非常接近Java。1.Scala的基准性能很接近Java,但确实没有Java好。但很多任务的单次执行的,性能损失在毫秒级不是什么问题;2.在大数据计算次数很多的情况下,我们全部写成命令式,而且还要考虑GC,JIT等基于JVM特性的优化。
首先,Scala不把程序员当傻子。当马丁?奥德斯基宣布Scala 2.12(http://www.scala-lang.org/news/roadmap-next)将要简化语法,推出Scala"Don Giovanni"项目的时候,在视频中说的很清楚:“Scala现在是为聪明人创造的,以后也是为聪明人服务的。”所以不同于Python让程序员用一种方法做所有事情,Scala提供一整套工具,让程序员自由选择,无论是mutable数据结构,immutable数据结构,并行(parallel)数据结构。然后在这些选择中,Scala再针对他们进行算法层面的特殊优化。Scala相信程序员的聪明才智,让程序员自行选择合适的结构,以针对变化万千的任务需求,这点是Scala做得极好的地方。
供需链的Scala的供需链
荷兰Scala以开发高水平的跨国商务软件而闻名于世。Scala集成的电子商务管理解决方案,具有财务及资源管理、市场营销管理、供应流程管理、服务及项目流程管理、制造及商务智能管理等方面。Scala的供需链是在当前具有先进管理思想的ERP的基础上又吸收了供需链管理的敏捷制造技术,适用于面向客户的管理模式和企业动态联盟企业。一般企业流程主要是在以下三个部门之间进行的: 主生产计划主生产计划(MasterProductionSchedule)模块可根据销售预测和销售定单对产成品制定一个长期的生产计划,同时企业也可根据自己的实际情况进行手工调整从而基本上满足企业的长期需求。在这里不会对原材料进行具体的需求分析。实际上,MPS是为管理部门提供一种手段,以授权和控制劳动力水平、库存投资、关键资源负荷(草拟生产能力计划)和支持客户服务的现金流量、获利能力及投资目标。同时,MPS程序还可以驱动物料需求计划,使业务计划与日常操作计划互连。除预测信息外,输入MPS的还有库存状态、客户订单和安全库存水平。有了主生产计划,就可以运行物料需求计划(MaterialRequirementsPlanning),它是建立在MRPII理论基础上的。根据主生产计划、库存情况及物料清单,MPR就能把主生产计划转换为生产和采购建议,其中包括前置期、批量大小、车间日程表、计划工程变更和库存状态等。系统不仅给出一个完整的有关整个生产过程的MRP报表,同时对生产车间、工序等做生产能力需求分析(CapacityRequirementsPlanning),它是把MRP程序产生的计划工作量和生产管理模块中发放的加工单加以结合处理,将结果以图形的形式表现出来,企业可通过改变利用率或增加另一班次,模拟每个加工中心改变生产能力后的状况。张先生所做的就是由销售订单模块的报价单功能向他的客户针对自行车生产提供一个详细的报价,只有等客户认为价钱合理,可以成交,并将信息反馈给张先生后,张先生只需在计算机上点击几下,报价单便自动转换为订单,同时张先生不用自己跑到库房查询存货情况,计算机会告诉他是否有足够的存货,是否还需组织生产。如果客户催货比较紧,张先生可通过批次管理制定该货出厂可以是第几批,然后系统会提交一份交货时间表。不过由于自行车生意的确不错,库存明显不够,需要组织生产。这时MPS根据本厂的实际情况会向张先生提供一个长期的生产计划。而MRP则将这个计划转换为具体的生产和采购建议。尤其它能将物料清单分解、细化,比如生产一辆自行车需要轴承、螺丝、螺母、铁丝等等,而这些原材料库存不足,需要采购,至于采购多少,生产多少,MRP会在建议中给出。生产作业在ERP的生产流程中,一旦确立了生产计划,并正确定义了人员、机器和工具等生产资源,Scala的订单计划/生产作业控制(OrderPlanning/Productionactivitycontrol)模块就能帮助企业计划、跟踪并分析加工单。当加工单发出后,构成该产品的物料将被扣留,并自动降低相关工作中心的有效工作能力。 在创建加工单(creatingaworkorder)后,加工单可以包含很多信息,如仓库、优先级、主管、客户和客户订单号、交货地址、附注以及会计核算明细表等。做完前置期计算(Lead),输入有关物料和操作程序的全部数据后,就可以发放加工单(Releasingaworkorder),发出的加工单将为订单预留出必要物料。除加工单的起始日期外,也可以有选择地将所需的物料预留到其它日期。这个过程就是物料预留(Reservationofmarerials)。每一种物料/产品都有一份MRP记录(MRPrecord),表明其在库存余额中的预期走势。此记录除了表明实际库存余额外,还能显示出该物料/产品有关的预期事项,如客户的预定、加工单或预期从生产部门收到的产品等。有了加工单,从库存领取物料以后,便进入了车间控制(ShopFloorControl)。生产设备的瓶颈矛盾一直是制约产量的重要因素。车间控制模块提供有关工具,使资源、原材料和各种组件的物流达到平衡,从而实现对加工单的有效执行。其主要功能包括:给每个加工单制定优先级、排程、打印加工单文件、提供在产品信息、为加工单计划更新加工单状态等。车间人员只要通过查看计算机屏幕,就可知道有关生产变化和特殊操作指令。这其中车间管理模块可以支持多个场地采用无纸生产(Paperlessproduction)的要求,企业可以为每个生产中心或操作者编制屏幕格式,操作者可以检查与每种加工单相关的全部数据,并对主要信息进行监控。而生产统计(Productionstatistics)模块可以提供有关生产过程状况的重要信息,是监控生产过程的一种工具。操作者可以通过这一功能查看生产能力、利用率、前置期、废品等数据,以及上述数据的生成原因等。有了这套软件,生产变得更加按部就班,并且效率高。自行车生产第一线的主管要做的就是在接到张先生的生产建议后将其转为生产加工单,然后根据加工单向仓库领料,不会产生不必要的浪费或材料短缺。由车间控制监控生产的每一个环节。由于全部通过计算机,所以也实现了无纸生产。等客户所需的自行车生产完毕后,入库,根据交货时间及时交货,张先生就可以和客户满意地握手了。 采购在Scala的采购模块(PurchaseOrdersModule)中,具备采购建设功能,企业根据自身情况加以调整,并根据供货商交货期、预算销售额、实际销售额、合理订购数量等,系统自动生成一个详细的采购计划(Purchaseplanning),并能对订单产生出默认的供货商。确定了采购计划后,企业就可以通过采购订单建议程序来自动生成采购订单(PurchaseOrdes),当然企业自己也可以手工输入订单。订单一旦生成,就被编入企业库存计划,并计入采购约定成本。订单打印出来后寄给供应商,供应商就可以发货了。接受货物(receivinggoods)仅以实际交货数量或以发票给出的数量为准。在这两种情况下,采购成本功能都会把库存价值和会计核算内容更新。接受到的货物可被分配到不同的仓库。企业可以通过批次管理(BatchControl)功能规定批号、供货商标记和有效期,以便日后识别。各批次直到通过了质量管理检验才能发出。当然,在采购订单及总分类帐模块中还会存在未交货的订购货物,称之为途中货物(Goodsintransit),对采购订单条目进行简单的查询,可以使企业对收货和发货有一个全面了解。因为Scala软件很好地把采购管理模块与应付分类帐模块良好地结合在一起,因此可以把所有与采购订单相对应的所有发票(Invoices)输入到这个模块中,这样企业就确保了采购成本的计算无误,使管理和授权程序更加简单。输完发票后,系统会生成应付帐款凭证。根据这条供需链,该凭证就会进入财务应付分类帐模块。有了这套软件,采购部主管就可根据张先生提供的采购建议,做适当调整,生成采购订单以组织采购自行车生产所必须的原材料,并入库做好记录。这一切都按照计划进行,所以不存在突然加班的问题。当然采购的发票可以自动生成,也可以人工输入,这些都会转入财务中去,节省了大量的时间。销售订单和计划 由Scala供需链流程来看,根据市场需求(Marketdemand),企业向客户提交一个报价单,经过双方协商,最终形成一个销售订单反馈到企业。Scala的销售订单模块(SalesOrdermodule)广泛的功能可对销售和分销过程的各个阶段提供支持,由于销售订单模块与库存、采购和生产模块紧密结合,企业能够在销售的同时,制定生产或采购明细表,从而保证及时交货。企业可以通过该模块的报价单(Quotations)为客户提供报价,当客户接受报价时,企业自动把报价单转换为订单,同时报价报表可以提供一份有效的及过期的报价单总汇。在订单(Orders)功能中,由报价单转换过来的不同类型的订单和人工输入的订单,决定了后勤物资的流量。企业可以同时指定交货时间,如果不能在最后期限交货,交货计划系统会发出警告。通过批次管理(BatchControl),企业可以在订单输入时指定特定的批次。考虑库存的整体情况,根据先进先出的原则,系统可以提出一份交货时间表。于是,根据交货建议,Scala的销售定单模块(Salesordermodule)将提供所有必要的文件——订单确认书、取料清单、交货票据和发票等。在装运确认之后,定单就成为开票的依据。所售货物的成本和收入将自动记入Scala的定货分类帐模块(OrderLedgerModule)。库存管理产成品生产出来就要面临入库。从采购到交货,后勤流程全方位管理需要有良好的管理工具。Scala的库存管理(StockControl)模块可以单独使用,但当与采购订单和销售订单模块结合使用时,其功能会更强。库存管理模块的主要优点之一是能提供与每一库存项目相关的广泛数据。再订购水平、安全库存以及缺货报表功能有助于有效地管理库存和减少资金投入。用户可以通过库存管理模块管理货物系列号和物料清单,也能灵活进行批次管理,全面情况跟踪,并能支持广泛的服表程序。在库存项目管理主模块(Stockitemmaster)中可以对每一库存项目输入大量数据。每一库存项目都有自己的单位换算表。Scala按库存项给用户提供几十种价目表、特殊回扣以及定价有效期等。功能广泛的价格及成本计算程序使得对价格及成本的更改更加容易。通过产品的系列号(Serialnumber)和物料清单(BillofMaterial),用户可以灵活进行批次管理。同时,Scala还能进行库存评估(StockValuation),并在用户营业时也能进行全部库存盘点(Stocktaking)工作。 应付分类帐Scala应付分类帐(PurchaseLedger)模块为企业获得供应商信息和付款流程提供全面支持。它能协调采购和授权程序,为用户选择付款方式提供充分的灵活性,简化各种增值税和销售税率的会计核算过程,使法定申报程序变得更为简单。在供应商文件(Thesuppliermasterfile)中包含了用户所选定的供应商的一般信息。由于该模块会与Scala应收分类帐模块相互发生联系,因此可以显示用户应向供应商支付的净差额。在对细节管理不失控的情况下,集中采购功能(Centralizedpurchasingfunctions)能十分方便地进行集中采购。在发票管理(Invoiceprocessing)时,在报表中尚无发票的地方只有得到授权以后,发票才能登入会计核算明细帐。同时多样化的供应商借贷对照表和汇总表可以显示出各种未付的债务状况,并帮助处理预扣赋税。根据每张发票的到期信息,自动付款(Automaticpayments)将按照用户的选择提出付款建议。根据登帐日期或付款日期,系统计算出精确的税额,并定期打印出所需的增值税/销售税表。另外,为了帮助用户对企业财务状况进行评估,该模块还会提供付款预测(Paymentforecasting)。应收分类帐为改进企业现金流量,首先要建立一个有效的应收分类帐。Scala应收分类帐(SalesLeger)模块强大功能不仅能对收款程序起较好的作用,而且还能给销售业务和市场开发打下良好的基础。客户主文件(Thecustomermasterfile)包含企业客户群的一般信息,可帮助用户分析规划市场。在记录发票(Invoicing)时,Scala其它模块中的发票可自动传送到应收分类帐上,也可直接人工入帐。当用户打印发票日记帐时,总分类帐的各科目都将及时更新。同时利用发票合并功能可以实现几张发票的合并。作为应收分类帐中最重要的报表,余额汇总报表(BalanceSummaryReport)中列有于用户相关的全部来往项目。考虑到客户的付款习惯,该系统可为用户提供付款(Payment)预测功能。例外呈报(Exceptionreporting)功能可极大地帮助用户根据自己的要求处理日常付款托收业务。根据某一时期的业务交易额,Scala可及时编制所有必要的增值税表及其它报表,并本地化输出。总分类帐会计核算是每个公司业务的核心。在Scala业务软件中,总分类帐(GeneralLedger)的实用性和灵活性恰恰表明了其它Scala业务模块的多样性。全部模块均具有10构面会计结构,可用于法定的,以及分析性的会计核算。用户可以任意使用一种构面呈报或查询实际或预算数目。把这些用途与Scala内置的多货币、多语种能力相结合,就会发现Scala是当今全球和本地会计核算和业务管理软件中功能最强大的系统之一。尤其值得一提的是,Scala的科目明细帐(AccountScheduleSystem)非常灵活,可充分满足不同地区的需要。帐户余额按科目类别储存,使用户能够在任何给定期间迅速呈报。凭证按日期储存,财政年度可以覆盖多达18个周期。在连续进行下一个周期之前。不必结帐。用户可以呈报从凭证文件中选定的任何凭证。帐户类型中还包含统计帐户,它可以保存法定会计核算中未包括的数据。Scala财务系统使用10种会计构面(Accountstringwithtendimensions),可以为用户的每一家分公司定义法定会计核算体系,并定义不同的呈报层次。当用户需要在几个科目、成本中心或其它会计核算构面之间分摊费用时,Scala的自动分摊(Automaticallocation)提供了99种可能性。当输入一份凭证时,系统将自动执行分摊。当然,任何凭证也可在定期分摊(Periodization)功能下实现待摊费用按若干个周期的分摊,而且可以在下一个财政年度,延续分摊。在进行对帐(Reconciliation)时,系统提供一个手边现金帐簿以核对凭证。通过输入银行凭证文件,用户可以进行人工或自动核对。如果用户在选项中选择固定资产管理(FixedAssetManagement),就可以对用户的固定资产进行全面管理。其中Scala提供了两种方法来针对一种固定资产进行折旧或重新估价计算。在生产流程中,当产成品入库后可过度到财务模块。系统可以自动计算出产成品成本(Costing),一般以标准成本来控制产成本。同时计算出实际成本(ActuallyCost),并通过统计模块对标准成本和实际成本的差异进行分析。它针对每个加工单(必须是关闭加工单为准),分析出物料的差异、人工的差异,得出人工的成本、料的成本及其它制造费用的成本。由于企业可以通过销售定单知道产品价格,因此知道了成本后,企业就可以知道利润。在差异分析完成后,进行差异分摊(VarianceAllocate),最后就可以汇入总帐。 另外,在总分类帐系统中,Scala还提供了红冲凭证、冲转凭证等,而报表模块(ReportofGeneralLedger)具有的各种财务报表(BalanceSheet,ProfitStatment)功能在财务系统中也极为重要,报表中列有与此有关的全部项目,通过对十个会计构面及其它特定标准的选择,可迅速提取相关信息,让用户从繁琐的报表作业中解脱出来。以上应付分类帐(PurchaseLedger)、应收分类帐(SalesLeger)、总分类帐(GeneralLedger)可简称PL、SL、GL,它们有着十分密切的联系。PL能协调采购和授权程序,为获得供应商信息和选择付款方式提供了充分的灵活性。而SL提供了实现财务和业务目标的有力工具,可全面记录货币明细和帐面价值,同时有助于分析和规划市场。最后,PL和SL都将在功能强大的GL中得以汇总和体现。
Scala编程语言简介
Scala编程语言近来抓住了很多开发者的眼球 如果你粗略浏览Scala的网站 你会觉得Scala是一种纯粹的面向对象编程语言 而又无缝地结合了命令式和函数式的编程风格 Christopher Diggins认为
不太久之前编程语言还可以毫无疑义地归类成 命令式 或者 函数式 Scala代表了一个新的语言品种 它抹平了这些人为划分的界限
根据David Rupp在博客中的说法 Scala可能是下下一代Java 这么高的评价让人不禁想看看它到底是什么东西
Scala有几项关键特性表明了它的面向对象的本质 例如 Scala中的每个值都是一个对象 包括基本数据类型(即布尔值 数字等)在内 连函数也是对象 另外 类可以被子类化 而且Scala还提供了基于mixin的组合(mixin based position)
与只支持单继承的语言相比 Scala具有更广泛意义上的类重用 Scala允许定义新类的时候重用 一个类中新增的成员定义(即相较于其父类的差异之处) Scala称之为mixin类组合
Scala还包含了若干函数式语言的关键概念 包括高阶函数(Higher Order Function) 局部套用(Currying) 嵌套函数(Nested Function) 序列解读(Sequence Comprehensions)等等
Scala是静态类型的 这就允许它提供泛型类 内部类 甚至多态方法(Polymorphic Method) 另外值得一提的是 Scala被特意设计成能够与Java和 NET互操作 Scala当前版本还不能在 NET上运行(虽然上一版可以) 但按照计划将来可以在 NET上运行
Scala可以与Java互操作 它用scalac这个编译器把源文件编译成Java的class文件(即在JVM上运行的字节码) 你可以从Scala中调用所有的Java类库 也同样可以从Java应用程序中调用Scala的代码 用David Rupp的话来说
它也可以访问现存的数之不尽的Java类库 这让(潜在地)迁移到Scala更加容易
这让Scala得以使用为Java 或者 编写的巨量的Java类库和框架 Scala会经常性地针对这几个版本的Java进行测试 Scala可能也可以在更早版本的Java上运行 但没有经过正式的测试 Scala以BSD许可发布 并且数年前就已经被认为相当稳定了
说了这么多 我们还没有回答一个问题 为什么我要使用Scala? Scala的设计始终贯穿着一个理念
创造一种更好地支持组件的语言 (《The Scala Programming Language》 Donna Malayeri)
也就是说软件应该由可重用的部件构造而成 Scala旨在提供一种编程语言 能够统一和一般化分别来自面向对象和函数式两种不同风格的关键概念
藉著这个目标与设计 Scala得以提供一些出众的特性 包括
* 面向对象风格
* 函数式风格
* 更高层的并发模型
Scala把Erlang风格的基于actor的并发带进了JVM 开发者现在可以利用Scala的actor模型在JVM上设计具伸缩性的并发应用程序 它会自动获得多核心处理器带来的优势 而不必依照复杂的Java线程模型来编写程序
* 轻量级的函数语法
o 高阶
o 嵌套
o 局部套用(Currying)
o 匿名
* 与XML集成
o 可在Scala程序中直接书写XML
o 可将XML转换成Scala类
* 与Java无缝地互操作
Scala的风格和特性已经吸引了大量的开发者 比如Debasish Ghosh就觉得
我已经把玩了Scala好一阵子 可以说我绝对享受这个语言的创新之处
lishixinzhi/Article/program/Java/hx/201311/26873
面向Java开发人员的Scala指南: 构建计算器,第1 部分
摘要 特定于领域的语言已经成为一个热门话题 很多函数性语言之所以受欢迎 主要是因为它们可以用于构建特定于领域的语言 鉴于此 在 面向 Java? 开发人员的 Scala 指南 系列的第 篇文章中 Ted Neward 着手构建一个简单的计算器 DSL 以此来展示函数性语言的构建 外部 DSL 的强大功能 他研究了 Scala 的一个新的特性 case 类 并重新审视一个功能强大的特性 模式匹配
上个月的文章发表后 我又收到了一些抱怨/评论 说我迄今为止在本系列中所用的示例都没涉及到什么实质性的问题 当然在学习一个新语言的初期使用一些小例子是很合理的 而读者想要看到一些更 现实的 示例 从而了解语言的深层领域和强大功能以及其优势 这也是理所当然的 因此 在这个月的文章中 我们来分两部分练习构建特定于领域的语言(DSL)— 本文以一个小的计算器语言为例
关于本系列
Ted Neward 将和您一起深入探讨 Scala 编程语言 在这个新的 developerWorks 系列 中 您将深入了解 Sacla 并在实践中看到 Scala 的语言功能 进行比较时 Scala 代码和 Java 代码将放在一起展示 但(您将发现)Scala 中的许多内容与您在 Java 编程中发现的任何内容都没有直接关联 而这正是 Scala 的魅力所在!如果用 Java 代码就能够实现的话 又何必再学习 Scala 呢?
特定于领域的语言
可能您无法(或没有时间)承受来自于您的项目经理给您的压力 那么让我直接了当地说吧 特定于领域的语言无非就是尝试(再一次)将一个应用程序的功能放在它该属于的地方 — 用户的手中
通过定义一个新的用户可以理解并直接使用的文本语言 程序员成功摆脱了不停地处理 UI 请求和功能增强的麻烦 而且这样还可以使用户能够自己创建脚本以及其他的工具 用来给他们所构建的应用程序创建新的行为 虽然这个例子可能有点冒险(或许会惹来几封抱怨的电子邮件) 但我还是要说 DSL 的最成功的例子就是 Microsoft? Office Excel 语言 用于表达电子表格单元格的各种计算和内容 甚至有些人认为 SQL 本身就是 DSL 但这次是一个旨在与关系数据库相交互的语言(想象一下如果程序员要通过传统 API read() / write() 调用来从 Oracle 中获取数据的话 那将会是什么样子)
这里构建的 DSL 是一个简单的计算器语言 用于获取并计算数学表达式 其实 这里的目标是要创建一个小型语言 这个语言能够允许用户来输入相对简单的代数表达式 然后这个代码来为它求值并产生结果 为了尽量简单明了 该语言不会支持很多功能完善的计算器所支持的特性 但我不也不想把它的用途限定在教学上 — 该语言一定要具备足够的可扩展性 以使读者无需彻底改变该语言就能够将它用作一个功能更强大的语言的核心 这意味着该语言一定要可以被轻易地扩展 并要尽量保持封装性 用起来不会有任何的阻碍
关于 DSL 的更多信息
DSL 这个主题的涉及面很广 它的丰富性和广泛性不是本文的一个段落可以描述得了的 想要了解更多 DSL 信息的读者可以查阅本文末尾列出的 Martin Fowler 的 正在进展中的图书 特别要注意关于 内部 和 外部 DSL 之间的讨论 Scala 以其灵活的语法和强大的功能而成为最强有力的构建内部和外部 DSL 的语言
换句话说 (最终的)目标是要允许客户机编写代码 以达到如下的目的
清单 计算器 DSL 目标
// This is Java using the Calculator String s = (( * ) + ) ; double result = tedneward calcdsl Calculator evaluate(s); System out println( We got + result); // Should be
我们不会在一篇文章完成所有的论述 但是我们在本篇文章中可以学习到一部分内容 在下一篇文章完成全部内容
从实现和设计的角度看 可以从构建一个基于字符串的解析器来着手构建某种可以 挑选每个字符并动态计算 的解析器 这的确极具诱惑力 但是这只适用于较简单的语言 而且其扩展性不是很好 如果语言的目标是实现简单的扩展性 那么在深入研究实现之前 让我们先花点时间想一想如何设计语言
根据那些基本的编译理论中最精华的部分 您可以得知一个语言处理器(包括解释器和编译器)的基本运算至少由两个阶段组成
● 解析器 用于获取输入的文本并将其转换成 Abstract Syntax Tree(AST) ● 代码生成器(在编译器的情况下) 用于获取 AST 并从中生成所需字节码 或是求值器(在解释器的情况下) 用于获取 AST 并计算它在 AST 里面所发现的内容
拥有 AST 就能够在某种程度上优化结果树 如果意识到这一点的话 那么上述区别的原因就变得更加显而易见了 对于计算器 我们可能要仔细检查表达式 找出可以截去表达式的整个片段的位置 诸如在乘法表达式中运算数为 的位置(它表明无论其他运算数是多少 运算结果都会是 )
您要做的第一件事是为计算器语言定义该 AST 幸运的是 Scala 有 case 类 一种提供了丰富数据 使用了非常薄的封装的类 它们所具有的一些特性使它们很适合构建 AST
case 类
在深入到 AST 定义之前 让我先简要概述一下什么是 case 类 case 类是使 scala 程序员得以使用某些假设的默认值来创建一个类的一种便捷机制 例如 当编写如下内容时
清单 对 person 使用 case 类
case class Person(first:String last:String age:Int){}
Scala 编译器不仅仅可以按照我们对它的期望生成预期的构造函数 — Scala 编译器还可以生成常规意义上的 equals() toString() 和 hashCode() 实现 事实上 这种 case 类很普通(即它没有其他的成员) 因此 case 类声明后面的大括号的内容是可选的
清单 世界上最短的类清单
case class Person(first:String last:String age:Int)
这一点通过我们的老朋友 javap 很容易得以验证
清单 神圣的代码生成器 Batman!
C:\Projects\Exploration\Scala>javap PersonCompiled from case scala public class Person extends java lang Object implements scala ScalaObject scala Product java io Serializable{ public Person(java lang String java lang String int); public java lang Object productElement(int); public int productArity(); public java lang String productPrefix(); public boolean equals(java lang Object); public java lang String toString(); public int hashCode(); public int $tag(); public int age(); public java lang String last(); public java lang String first();}
如您所见 伴随 case 类发生了很多传统类通常不会引发的事情 这是因为 case 类是要与 Scala 的模式匹配(在 集合类型 中曾简短分析过)结合使用的
使用 case 类与使用传统类有些不同 这是因为通常它们都不是通过传统的 new 语法构造而成的 事实上 它们通常是通过一种名称与类相同的工厂方法来创建的
清单 没有使用 new 语法?
object App{ def main(args : Array[String]) : Unit = { val ted = Person( Ted Neward ) }}
case 类本身可能并不比传统类有趣 或者有多么的与众不同 但是在使用它们时会有一个很重要的差别 与引用等式相比 case 类生成的代码更喜欢按位(biise)等式 因此下面的代码对 Java 程序员来说有些有趣的惊喜
清单 这不是以前的类
object App{ def main(args : Array[String]) : Unit = { val ted = Person( Ted Neward ) val ted = Person( Ted Neward ) val amanda = Person( Amanda Laucher ) System out println( ted == amanda: + (if (ted == amanda) Yes else No )) System out println( ted == ted: + (if (ted == ted) Yes else No )) System out println( ted == ted : + (if (ted == ted ) Yes else No )) }}/*C:\Projects\Exploration\Scala>scala Appted == amanda: Noted == ted: Yested == ted : Yes*/
case 类的真正价值体现在模式匹配中 本系列的读者可以回顾一下模式匹配(参见 本系列的第二篇文章 关于 Scala 中的各种控制构造) 模式匹配类似 Java 的 switch/case 只不过它的本领和功能更加强大 模式匹配不仅能够检查匹配构造的值 从而执行值匹配 还可以针对局部通配符(类似局部 默认值 的东西)匹配值 case 还可以包括对测试匹配的保护 来自匹配标准的值还可以绑定于局部变量 甚至符合匹配标准的类型本身也可以进行匹配
有了 case 类 模式匹配具备了更强大的功能 如清单 所示
清单 这也不是以前的 switch
case class Person(first:String last:String age:Int);object App{ def main(args : Array[String]) : Unit = { val ted = Person( Ted Neward ) val amanda = Person( Amanda Laucher ) System out println(process(ted)) System out println(process(amanda)) } def process(p : Person) = { Processing + p + reveals that + (p match { case Person(_ _ a) if a > => they re certainly old case Person(_ Neward _) => they e from good genes case Person(first last ageInYears) if ageInYears > => first + + last + is + ageInYears + years old case _ => I have no idea what to do with this person }) }}/*C:\Projects\Exploration\Scala>scala AppProcessing Person(Ted Neward ) reveals that they re certainly old Processing Person(Amanda Laucher ) reveals that Amanda Laucher is years old */
清单 中发生了很多操作 下面就让我们先慢慢了解发生了什么 然后回到计算器 看看如何应用它们
首先 整个 match 表达式被包裹在圆括号中 这并非模式匹配语法的要求 但之所以会这样是因为我把模式匹配表达式的结果根据其前面的前缀串联了起来(切记 函数性语言里面的任何东西都是一个表达式)
其次 第一个 case 表达式里面有两个通配符(带下划线的字符就是通配符) 这意味着该匹配将会为符合匹配的 Person 中那两个字段获取任何值 但是它引入了一个局部变量 a p age 中的值会绑定在这个局部变量上 这个 case 只有在同时提供的起保护作用的表达式(跟在它后边的 if 表达式)成功时才会成功 但只有第一个 Person 会这样 第二个就不会了 第二个 case 表达式在 Person 的 firstName 部分使用了一个通配符 但在 lastName 部分使用常量字符串 Neward 来匹配 在 age 部分使用通配符来匹配
由于第一个 Person 已经通过前面的 case 匹配了 而且第二个 Person 没有姓 Neward 所以该匹配不会为任何一个 Person 而被触发(但是 Person( Michael Neward ) 会由于第一个 case 中的 guard 子句失败而转到第二个 case)
第三个示例展示了模式匹配的一个常见用途 有时称之为提取 在这个提取过程中 匹配对象 p 中的值为了能够在 case 块内使用而被提取到局部变量中(第一个 最后一个和 ageInYears) 最后的 case 表达式是普通 case 的默认值 它只有在其他 case 表达式均未成功的情况下才会被触发
简要了解了 case 类和模式匹配之后 接下来让我们回到创建计算器 AST 的任务上
计算器 AST
首先 计算器的 AST 一定要有一个公用基类型 因为数学表达式通常都由子表达式组成 通过 + ( * ) 就可以很容易地看到这一点 在这个例子中 子表达式 ( * ) 将会是 + 运算的右侧运算数
事实上 这个表达式提供了三种 AST 类型
● 基表达式 ● 承载常量值的 Number 类型 ● 承载运算和两个运算数的 BinaryOperator
想一下 算数中还允许将一元运算符用作求负运算符(减号) 将值从正数转换为负数 因此我们可以引入下列基本 AST
清单 计算器 AST(src/calc scala)
package tedneward calcdsl{ private[calcdsl] abstract class Expr private[calcdsl] case class Number(value : Double) extends Expr private[calcdsl] case class UnaryOp(operator : String arg : Expr) extends Expr private[calcdsl] case class BinaryOp(operator : String left : Expr right : Expr) extends Expr}
注意包声明将所有这些内容放在一个包( tedneward calcdsl)中 以及每一个类前面的访问修饰符声明表明该包可以由该包中的其他成员或子包访问 之所以要注意这个是因为需要拥有一系列可以测试这个代码的 JUnit 测试 计算器的实际客户机并不一定非要看到 AST 因此 要将单元测试编写成 tedneward calcdsl 的一个子包
清单 计算器测试(testsrc/calctest scala)
package tedneward calcdsl test{ class CalcTest { import junit _ Assert _ @Test def ASTTest = { val n = Number( ) assertEquals( n value) } @Test def equalityTest = { val binop = BinaryOp( + Number( ) Number( )) assertEquals(Number( ) binop left) assertEquals(Number( ) binop right) assertEquals( + binop operator) } }}
到目前为止还不错 我们已经有了 AST
再想一想 我们用了四行 Scala 代码构建了一个类型分层结构 表示一个具有任意深度的数学表达式集合(当然这些数学表达式很简单 但仍然很有用) 与 Scala 能够使对象编程更简单 更具表达力相比 这不算什么(不用担心 真正强大的功能还在后面)
接下来 我们需要一个求值函数 它将会获取 AST 并求出它的数字值 有了模式匹配的强大功能 编写这样的函数简直轻而易举
清单 计算器(src/calc scala)
package tedneward calcdsl{ // object Calc { def evaluate(e : Expr) : Double = { e match { case Number(x) => x case UnaryOp( x) => (evaluate(x)) case BinaryOp( + x x ) => (evaluate(x ) + evaluate(x )) case BinaryOp( x x ) => (evaluate(x ) evaluate(x )) case BinaryOp( * x x ) => (evaluate(x ) * evaluate(x )) case BinaryOp( / x x ) => (evaluate(x ) / evaluate(x )) } } }}
注意 evaluate() 返回了一个 Double 它意味着模式匹配中的每一个 case 都必须被求值成一个 Double 值 这个并不难 数字仅仅返回它们的包含的值 但对于剩余的 case(有两种运算符) 我们还必须在执行必要运算(求负 加法 减法等)前计算运算数 正如常在函数性语言中所看到的 会使用到递归 所以我们只需要在执行整体运算前对每一个运算数调用 evaluate() 就可以了
大多数忠实于面向对象的编程人员会认为在各种运算符本身以外 执行运算的想法根本就是错误的 — 这个想法显然大大违背了封装和多态性的原则 坦白说 这个甚至不值得讨论 这很显然违背 了封装原则 至少在传统意义上是这样的
在这里我们需要考虑的一个更大的问题是 我们到底从哪里封装代码?要记住 AST 类在包外是不可见的 还有就是客户机(最终)只会传入它们想求值的表达式的一个字符串表示 只有单元测试在直接与 AST case 类合作
但这并不是说所有的封装都没有用了或过时了 事实上恰好相反 它试图说服我们在对象领域所熟悉的方法之外 还有很多其他的设计方法也很奏效 不要忘了 Scala 兼具对象和函数性 有时候 Expr 需要在自身及其子类上附加其他行为(例如 实现良好输出的 toString 方法) 在这种情况下可以很轻松地将这些方法添加到 Expr 函数性和面向对象的结合提供了另一种选择 无论是函数性编程人员还是对象编程人员 都不会忽略到另一半的设计方法 并且会考虑如何结合两者来达到一些有趣的效果
从设计的角度看 有些其他的选择是有问题的 例如 使用字符串来承载运算符就有可能出现小的输入错误 最终会导致结果不正确 在生产代码中 可能会使用(也许必须使用)枚举而非字符串 使用字符串的话就意味着我们可能潜在地 开放 了运算符 允许调用出更复杂的函数(诸如 abs sin cos tan 等)乃至用户定义的函数 这些函数是基于枚举的方法很难支持的
对所有设计和实现的来说 都不存在一个适当的决策方法 只能承担后果 后果自负
但是这里可以使用一个有趣的小技巧 某些数学表达式可以简化 因而(潜在地)优化了表达式的求值(因此展示了 AST 的有用性)
● 任何加上 的运算数都可以被简化成非零运算数 ● 任何乘以 的运算数都可以被简化成非零运算数 ● 任何乘以 的运算数都可以被简化成零
不止这些 因此我们引入了一个在求值前执行的步骤 叫做 simplify() 使用它执行这些具体的简化工作
清单 计算器(src/calc scala)
def simplify(e : Expr) : Expr = { e match { // Double negation returns the original value case UnaryOp( UnaryOp( x)) => x // Positive returns the original value case UnaryOp( + x) => x // Multiplying x by returns the original value case BinaryOp( * x Number( )) => x // Multiplying by x returns the original value case BinaryOp( * Number( ) x) => x // Multiplying x by returns zero case BinaryOp( * x Number( )) => Number( ) // Multiplying by x returns zero case BinaryOp( * Number( ) x) => Number( ) // Dividing x by returns the original value case BinaryOp( / x Number( )) => x // Adding x to returns the original value case BinaryOp( + x Number( )) => x // Adding to x returns the original value case BinaryOp( + Number( ) x) => x // Anything else cannot (yet) be simplified case _ => e } }
还是要注意如何使用模式匹配的常量匹配和变量绑定特性 从而使得编写这些表达式可以易如反掌 对 evaluate() 惟一一个更改的地方就是包含了在求值前先简化的调用
清单 计算器(src/calc scala)
def evaluate(e : Expr) : Double = { simplify(e) match { case Number(x) => x case UnaryOp( x) => (evaluate(x)) case BinaryOp( + x x ) => (evaluate(x ) + evaluate(x )) case BinaryOp( x x ) => (evaluate(x ) evaluate(x )) case BinaryOp( * x x ) => (evaluate(x ) * evaluate(x )) case BinaryOp( / x x ) => (evaluate(x ) / evaluate(x )) } }
还可以再进一步简化 注意一下 它是如何实现只简化树的最底层的?如果我们有一个包含 BinaryOp( * Number( ) Number( )) 和 Number( ) 的 BinaryOp 的话 那么内部的 BinaryOp 就可以被简化成 Number( ) 但外部的 BinaryOp 也会如此 这是因为此时外部 BinaryOp 的其中一个运算数是零
我突然犯了作家的职业病了 所以我想将它留予读者来定义 其实是想增加点趣味性罢了 如果读者愿意将他们的实现发给我的话 我将会把它放在下一篇文章的代码分析中 将会有两个测试单元来测试这种情况 并会立刻失败 您的任务(如果您选择接受它的话)是使这些测试 — 以及其他任何测试 只要该测试采取了任意程度的 BinaryOp 和 UnaryOp 嵌套 — 通过
结束语
显然我还没有说完 还有分析的工作要做 但是计算器 AST 已经成形 我们无需作出大的变动就可以添加其他的运算 运行 AST 也无需大量的代码(按照 Gang of Four 的 Visitor 模式) 而且我们已经有了一些执行计算本身的工作代码(如果客户机愿意为我们构建用于求值的代码的话)
lishixinzhi/Article/program/Java/hx/201311/25735
scala ide是干什么用的
Scala是一门现代的多范式编程语言,志在以简练、优雅及类型安全的方式来表达常用编程模式。它平滑地集成了面向对象和函数语言的特性。
Scala是面向对象的:Scala是一个纯面向对象语言,在某种意义上来讲所有数值都是对象。对象的类型和行为是由class和trait来描述的。Class的抽象可由子类化和一种灵活的基于mixin的组合机制(它可作为多重继承的简单替代方案)来扩展。
Scala是函数式的: Scala还是一个函数式语言,在某种意义上来讲所有函数都是数值。Scala为定义匿名函数提供了一种轻量级的语法,它支持高阶(higher-order)函数、允许函数嵌套、支持局部套用(currying)。Scala的case类及其内置支持的模式匹配模型代数类型在许多函数式编程语言中都被使用。
Scala是静态类型的:Scala配备了一套富有表现力的类型系统,该抽象概念以一种安全的和一致的方式被使用。
Scala是可扩展的:Scala的设计承认了实践事实,领域特定应用开发通常需要领域特定语言扩展。Scala提供了一个独特的语言组合机制,这可以更加容易地以类库的形式增加新的语言结构:两者结合使用可方便地定义新语句,无需扩展语法,也无需使用类似宏的元编程工具。
任何方式可以被用作中缀(infix)或后缀(postfix)操作符
闭包按照所期望的类型(目标类型)自动地被构造
Scala可与Java和.NET进行互操作:Scala设计时就考虑了与流行编程环境良好交互,如Java 2运行时环境(JRE)和 .NET框架(CLR)。特别是与主流面向对象语言,如Java和C#尽量无缝交互。Scala有像Java和C#一样的编译模型(独立编译,动态装载类),允许访问成千上万的高质量类库。
对于某些开发者来说,这些刺激已足以引诱他们脱离Java进入Scala世界。但对另外一些开发者来说,它们并没有为Java世界里当前正在演绎的日复一日的编程活动提供更多好处。
在一篇名为“Scala:集Ruby和Java之所长”的博文中,Ian讲述了或许不应在Java和Scala之间做出选择,相反,相对于选择其它语言如Ruby,选择使用Java和Scala的混合物是的另一种选择:
许多开发者热爱Ruby,不过他们不能从中获取足够的东西。它可能是最具侵略性的语言之一,因为Java才是第一个到场的。人们总是引证Ruby的灵活而可扩展的语法、闭包等特性,以及其代码如何简明和具有表现力。
例如,你可以用一个简单语法创建一个Map(Ruby称之为“hashes”,尽管hashtable只是map一种可能的实现方式),如:
numberMap = {"one" => 1, "two" => 2, "three" => 3}
Java与之对等的语句显得颇为冗长:
Map
numberMap = new HashMap
(); numberMap.put("one", 1); numberMap.put("two", 2); numberMap.put("three", 3);
那么Scala怎么样呢?让我们看看Scala中map的例子:
var numberMap = Map("one" -> 1, "two" -> 2, "three" -> 3)
你会注意到它看上去非常类似等价的Ruby代码,但是这儿有一些重要区别。特别是,就像Java,Scala编译器知道numberMap使用String作为键,Integer作为值。与Java不同的是,你无需告知,它本身就能领会这一点!这称为“类型推理(type inference)”。
这意味着如果你试图给numberMap增加一个新的键值对,但是要使用Integer作为键,String作为值,Scala将在你试图编译它时立刻报错(或者你的IDE将立刻警告你)。使用Ruby,只有当你运行你的软件并试图从该Map中找回该键和值时,得到的分别是Integer和String而不是所期望的String和Integer,这时才会导致报错。
过分强调编译时类型检查节省多少多少时间是困难的,但它消除了所有类在执行时将会产生的bug。Scala给你带来了这一好处,而且代码并不繁琐。
为更进一步在一个小例子中展现代码量的缩减,Ted Neward研究了开发同一个类,用Java、C#、Virual Basic、Ruby和Scala的区别。请参考其博文Scala pt 2:简短。
Ian继续指出:
Scala还有一连串其它好的Ruby特性(Java所缺乏的),包括闭包,以及非常适合“领域特定语言”的可塑性语法。它拥有所有这些特性,而且结合了静态类型好处。
David MacIver在其博文说正经的,为什么选择Scala?中分享了他对于面向对象编程、面向模块编程、静态类型、函数编程以及该语言中他所喜欢的未言明特性的观点。他补充道:
Scala离完美还差得远。它有一些语法缺陷,一些由Java带来的问题,一个有适度问题的编译器以及一堆你记不住的琐碎特性和边界情况(edge case)。然而,我发现这些问题除了烦你之外并不真正产生什么后果。如果只是想坐下来书写好的代码,该语言的核心是强大的和非常有用的。
为了提供一个均衡的观点,David在其博文中接着探讨了为什么不选Scala,文中他阐述了一些边界情况(edge case)。作为总结,David有如下评论:
总而言之,我发现这些只是增加了一些烦心事。它仍是我最喜欢的JVM语言,但是你的看法将取决于你怎样搁置那些对你来说可能是更重要的需要优先考虑的事情。
为了展现Scala是一门不断成熟的语言,Programming in Scala一书很快将会出版。如果等不及,Artima网站上有该书PDF格式的预印版。
数据分析常用的编程语言有哪些
数据分析常用的编程语言有Python、R、SQL、Scala、Julia。
编程是软件开发的基础,大数据分析是包括计算机科学在内的多个领域的集合。它涉及科学过程和方法的使用,以分析数据并从中得出结论。为此角色设计的特定编程语言将执行这些方法。为了成为熟练的大数据分析家,必须掌握以下大数据分析编程语言。
1、Python
它是易于使用的基于解释器的高级编程语言。Python是一种通用语言,具有用于多个角色的大量库。由于其易于学习的曲线和有用的库,它已成为大数据分析最受欢迎的选择之一。Python观察到的代码可读性也使它成为Data Science的流行选择。
由于大数据分析家可以解决复杂的问题,因此拥有一种易于理解的语言是理想的。Python使用户更容易在遵循所需算法标准的同时实现解决方案。
Python支持多种库。大数据分析中解决问题的各个阶段都使用自定义库。解决大数据分析问题涉及数据预处理,分析,可视化,预测和数据保存。为了执行这些步骤,Python拥有专用的库,例如–Pandas,Numpy,Matplotlib,SciPy,scikit-learn等。
此外,高级的Python库(例如Tensorflow,Keras和Pytorch)为大数据分析家提供了深度学习工具。
2、R
对于面向统计的任务,R是理想的语言。与Python相比,有抱负的大数据分析家可能不得不面对陡峭的学习曲线。R专门用于统计分析。因此,它在统计学家中非常受欢迎。如果您想深入了解数据分析和统计信息,那么R是您选择的语言。R的唯一缺点是它不是通用编程语言,这意味着它不用于统计编程以外的任务。
R在CRAN的开放源代码存储库中有10,000多个软件包,可满足所有统计应用程序的需求。R的另一个强项是它处理复杂线性代数的能力。这使得R不仅适用于统计分析而且适用于神经网络。R的另一个重要功能是其可视化库ggplot2。
还有其他工作室套件,例如tidyverse和Sparklyr,它们为Apache R提供基于Apache Spark的接口。RStudio等基于R的环境使连接数据库变得更加容易。它具有一个称为“RMySQL”的内置软件包,该软件包提供R与MySQL的本地连接。所有这些功能使R成为核心大数据分析家的理想选择。
3、SQL
SQL被称为“大数据分析的关键”,SQL是大数据分析家必须具备的最重要技能。SQL或“结构化查询语言”是用于从称为关系数据库的有组织数据源中检索数据的数据库语言。在大数据分析中,SQL用于更新,查询和操作数据库。
作为大数据分析家,了解如何检索数据是工作中最重要的部分。SQL是大数据分析家的“辅助武器”,这意味着它提供的功能有限,但对于特定角色至关重要。它具有多种实现,例如MySQL,SQLite,PostgreSQL等。
4、Scala
Scala stand是在JVM上运行的Java编程语言的扩展。它是一种通用编程语言,具有面向对象技术和功能编程语言的功能。您可以将Scala与大数据平台Spark结合使用。当处理大量数据时,这使Scala成为理想的编程语言。
Scala提供了与Java的完全互操作性,同时与Data保持了紧密的联系。作为大数据分析家,必须对使用编程语言充满信心,以便以所需的任何形式雕刻数据。Scala是专门为此角色创建的高效语言。Scala的最重要特征是其促进大规模并行处理的能力。但是,Scala的学习曲线比较陡峭,我们不建议初学者使用。
5、Julia
Julia是最近开发的编程语言,最适合科学计算。它像Python一样简单,因此广受欢迎,并且具有C语言的迅捷性能。这使Julia成为需要复杂数学运算的领域的理想语言。作为大数据分析家,您将研究需要复杂数学的问题。Julia能够以很高的速度解决此类问题。
尽管Julia由于其最新开发而在其稳定版本中遇到了一些问题,但它现在已被广泛认可为人工智能语言。