scala计算1到100的和(编写一个函数,返回3个数中最大的两个数的和.)

2024-06-30 16:56:35 20

scala计算1到100的和(编写一个函数,返回3个数中最大的两个数的和.)

本文目录

编写一个函数,返回3个数中最大的两个数的和.

#include《iostream》using namespace std;template 《typename T》T find(T a,T b,T c){T max;if(a》=b)max=a;elsemax=b;if(max《=c)max=c;return max;}void main(){int a,b,c;//这里的类型可以随便设int float double等数值型都行由于函数是模板类函数cin》》a》》b》》c;cout《《endl;cout《《find(a,b,c)《《endl;}

scala用函数库返回随机值

scala用函数库返回随机值:scala》 val l = List(5,4,3,6,2,1) l。

 List = List(6, 5, 4, 3, 2, 1) 。

而后觉得Java有太多羁绊而发明了Scala。 Scala编译器和类型系统非常强大,它的目标是尽量把软件错误消灭在编写过程中。 Scala类型系统是图灵完备的,甚至可以在编译期间解决问题。

scala技巧:

1、不要陷入C++一样的、不断膨胀的问题里,留下太多的选择,且没有清晰的最佳实践。这导致每个人都在选择不同的子集。要提供适应的指导。

2、记住,反对不良的设计功能与增加新功能同等重要——这很残酷。

3、考虑拆分语言为生产环境创建可行的标准。为学术世界节省成本是一个明智的选择。迎合企业的需要,获得更大的采用。

4、库的编写者应该看看Java API,确认是否应该有功能调用或结构化功能,为了更好的阅读。不要为了流动性在跳跃太大来与Ruby竞争。

scala怎么将map转换为数组

val m=Map( 1 -》 100 , 2-》 200, 3-》 300)val a=m.toVector

a: Vector = Vector((1,100), (2,200), (3,300))

数组中放的是turple

scala case class 这时候该怎么用

OK,让我们一劳永逸的解决这个问题吧,让大家见识一下Scala的强大:给定一个字符串,自动转换为需要的case class

比如:

  • 给定字符串"zhangsan,100,34",定义了case class Person(name: String, id: Int, age: Int),就能自动由字符串得到Person(zhangsan, 100, 34)

  • 给定字符串"100,300,400",定义了case class Vec(x: Int, y: Int, z: Int),就能自动由字符串得到Vec(100, 300, 400)

  • 首先给出最终的实现效果:
  • @ case class Person(name: String, id: Int, age: Int)defined class Person@ Str2Class("100,200,300").getres5: Vec = Vec(100, 200, 300)
  • 下面是具体的实现代码:
  • object Str2Class {
  •  import util.{ Failure, Success, Try }
  •  trait Conveter }
  •  object Conveter {
  •    def apply = c
  •    implicit object s2s extends Conveter {
  •      def convert(text: String) = Try(text)
  •    }
  •    implicit object s2i extends Conveter {
  •      def convert(text: String) = Try(text.toInt)
  •    }
  •  }
  •  import shapeless._
  •  trait Parser }
  •  object Parser {    
  •    def apply) = p
  •    def fromFun {
  •      def parse(xs: Seq) = f(xs)
  •    }
  •    implicit object HNilParser extends Parser {
  •      def parse(xs: Seq = xs match {
  •        case Seq() =》 Success(HNil)
  •        case _   =》 Failure(new RuntimeException("More items than expected."))
  •      }
  •    }
  •    implicit def hListParser = fromFun {
  •      case x +: rs =》 for(xv 《- Conveter.parse(rs)) yield xv::rv
  •      case Seq() =》 Failure(new RuntimeException("Less items than expected."))
  •    }
  •  }
  •  trait LineParser {
  •    def apply(text: String)
  •                        (implicit gen: Generic.Aux =
  •      p.parse(text.split(",")) map (gen.from)
  •  }
  •  def apply{}}
  • ==================原回答===================

    Here we go:

  • @ import shapeless._@ import syntax.std.traversable._@ import syntax.std.tuple._@ case class data(a: Int, b: Int, c: Int, d: Int, e: Int)defined class data@ type DATA = Int :: Int :: Int :: Int :: Int :: HNildefined type DATA@ val arr = "1\t2\t3\t4\t5".split(’\t’).map(_.toInt)arr: Array = Array(1, 2, 3, 4, 5)
  •                                               @ val myData = data.tupled(arr.toHList.get.tupled)myData: data = data(1, 2, 3, 4, 5)

idea里scala里的map方法需要添加什么头文件

不用吧Map结构是一种非常常见的结构,在各种程序语言都有对应的api,由于Spark的底层语言是Scala,所以有必要来了解下Scala中的Map使用方法。(1)不可变Map特点:api不太丰富如果是var修饰,引用可变,支持读写如果是val修饰,引用不可变,只能写入一次值,其后只读var a:Map=Map("k1"-》1,"k2"-》2)//初始化构造函数a += ("k3"-》3)//添加元素a += ("k4"-》4)//添加元素a += ("k1"-》100)//已经存在添加元素会覆盖a -= ("k2","k1")//删除元素// a("k1") = "foo"//不支持println(a.contains("k6"))//是否包含某元素println(a.size)//打印大小println(a.get("k1").getOrElse("default")) //根据key读取元素,不存在就替换成默认值a.foreach{case (e,i) =》 println(e,i)} //遍历打印1for( (k,v)《-a ) println(k,v) //遍历打印2println(a.isEmpty)//判断是否为空a.keys.foreach(println)//只打印keya.values.foreach(println)//只打印valuea=Map()//数据清空使用再次newprintln(a.size) a.toSeq.sortBy(_._1)//升序排序 keya.toSeq.sortBy(_._2)//升序排序 valuea.toSeq.sortWith(_._1》_._1) //降序排序 keya.toSeq.sortWith(_._2》_._2) //降序排序 value//下面自定义按英文字母或数字排序implicit val KeyOrdering=new Ordering {override def compare(x: String, y: String): Int = {x.compareTo(y)}}println(a.toSeq.sorted)(2)可变Map例子特点:api丰富与Java中Map基本类似如果是var修饰,引用可变,支持读写如果是val修饰,引用不可变,支持读写def map3(): Unit ={ //不可变Map+var关键词修饰例子var a:scala.collection.mutable.Map=scala.collection.mutable.Map("k1"-》1,"k2"-》2)//初始化构造函数a += ("k3"-》3)//添加元素a += ("k4"-》4)//添加元素a += ("k1"-》100)//已经存在添加元素会覆盖a += ("k1"-》100,"k9"-》9)//添加多个元素a -= ("k2","k1")//删除元素a ++= List("CA" -》 23, "CO" -》 25)//追加集合a --= List("AL", "AZ")//删除集合a.retain((k,v)=》 k=="k1")//只保留等于k1元素,其他的删除a.put("put1",200)//puta.remove("k2")//removea.clear()//清空a("k3")=100//支持println(a.contains("k6"))//是否包含某元素println(a.size)//打印大小println(a.get("k1").getOrElse("default")) //根据key读取元素,不存在就替换成默认值a.foreach{case (e,i) =》 println(e,i)} //遍历打印1for( (k,v)《-a ) println(k,v) //遍历打印2println(a.isEmpty)//判断是否为空a.keys.foreach(println)//只打印keya.values.foreach(println)//只打印valuea=scala.collection.mutable.Map()//引用能变println(a.size) a.toSeq.sortBy(_._1)//排序 keya.toSeq.sortBy(_._2)//排序 valuea.toSeq.sortWith(_._1》_._1) //降序排序 keya.toSeq.sortWith(_._2》_._2) //降序排序 value//下面自定义按英文字母或数字排序implicit val KeyOrdering=new Ordering {override def compare(x: String, y: String): Int = {x.compareTo(y)}}println(a.toSeq.sorted)}

大神求助,IntelliJ运行Scala程序问题

打成Jar包,直接用spark-submit 方式运行就可以成功,直接用IntelliJ就总是失败,不知道怎么回事,求大神指点。程序是object HelloSpark {def main(args:Array): Unit ={if(args.length!=2){System.err.println("Usage:HelloSpark 《Input》 《Output》")System.exit(1)}val conf = new SparkConf().setAppName("helloSpark").setMaster("spark://master:7077").set("spark.executor.memory", "1g").set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")val sc = new SparkContext(conf)sc.textFile(args(0)).map(_.split("\t")).filter(_.length==6).map(x=》(x(1),1)).reduceByKey(_+_).map(x=》(x._2,x._1)).sortByKey(false).map(x=》(x._2,x._1)).saveAsTextFile(args(1))sc.stop()}这是网上的一个实例,步骤都是一步一步来的。16/02/23 16:39:53 WARN TaskSetManager: Lost task 0.0 in stage 0.0 (TID 0, worker1): java.lang.ClassNotFoundException: com.spark.firstApp.HelloSpark$$anonfun$2at java.net.URLClassLoader.findClass(URLClassLoader.java:381)at java.lang.ClassLoader.loadClass(ClassLoader.java:424)at java.lang.ClassLoader.loadClass(ClassLoader.java:357)at java.lang.Class.forName0(Native Method)at java.lang.Class.forName(Class.java:348)at org.apache.spark.serializer.JavaDeserializationStream$$anon$1.resolveClass(JavaSerializer.scala:68)at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1613)at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1993)at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1918)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1993)at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1918)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)......at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:213)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)at java.lang.Thread.run(Thread.java:745)16/02/23 16:39:53 INFO TaskSetManager: Starting task 0.1 in stage 0.0 (TID 2, worker0, partition 0,NODE_LOCAL, 2134 bytes)16/02/23 16:39:53 INFO TaskSetManager: Lost task 1.0 in stage 0.0 (TID 1) on executor worker2: java.lang.ClassNotFoundException (com.spark.firstApp.HelloSpark$$anonfun$2) 16/02/23 16:39:53 INFO TaskSetManager: Starting task 1.1 in stage 0.0 (TID 3, worker2, partition 1,NODE_LOCAL, 2134 bytes)16/02/23 16:39:53 INFO TaskSetManager: Lost task 1.1 in stage 0.0 (TID 3) on executor worker2: java.lang.ClassNotFoundException (com.spark.firstApp.HelloSpark$$anonfun$2) 16/02/23 16:39:53 INFO TaskSetManager: Starting task 1.2 in stage 0.0 (TID 4, worker1, partition 1,NODE_LOCAL, 2134 bytes)16/02/23 16:39:53 INFO TaskSetManager: Lost task 1.2 in stage 0.0 (TID 4) on executor worker1: java.lang.ClassNotFoundException (com.spark.firstApp.HelloSpark$$anonfun$2) 16/02/23 16:39:53 INFO TaskSetManager: Starting task 1.3 in stage 0.0 (TID 5, worker1, partition 1,NODE_LOCAL, 2134 bytes)16/02/23 16:39:53 INFO TaskSetManager: Lost task 1.3 in stage 0.0 (TID 5) on executor worker1: java.lang.ClassNotFoundException (com.spark.firstApp.HelloSpark$$anonfun$2) 16/02/23 16:39:53 ERROR TaskSetManager: Task 1 in stage 0.0 failed 4 times; aborting job16/02/23 16:39:53 INFO TaskSchedulerImpl: Cancelling stage 016/02/23 16:39:53 INFO TaskSchedulerImpl: Stage 0 was cancelled16/02/23 16:39:53 INFO DAGScheduler: ShuffleMapStage 0 (map at HelloSpark.scala:20) failed in 10.015 s16/02/23 16:39:53 INFO DAGScheduler: Job 0 failed: sortByKey at HelloSpark.scala:21, took 10.156984 sException in thread "main" org.apache.spark.SparkException: Job aborted due to stage failure: Task 1 in stage 0.0 failed 4 times, most recent failure: Lost task 1.3 in stage 0.0 (TID 5, worker1): java.lang.ClassNotFoundException: com.spark.firstApp.HelloSpark$$anonfun$2at java.net.URLClassLoader.findClass(URLClassLoader.java:381)at java.lang.ClassLoader.loadClass(ClassLoader.java:424)at java.lang.ClassLoader.loadClass(ClassLoader.java:357)at java.lang.Class.forName0(Native Method)at java.lang.Class.forName(Class.java:348)at org.apache.spark.serializer.JavaDeserializationStream$$anon$1.resolveClass(JavaSerializer.scala:68)at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1613)at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1993)at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1918)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1993)at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1918)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1993)at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1918)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)at scala.collection.immutable.$colon$colon.readObject(List.scala:362)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:497)at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017)at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1896)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1993)at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1918)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1993)at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1918)......at org.apache.spark.serializer.JavaSerializerInstance.deserialize(JavaSerializer.scala:115)at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:64)at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:41)at org.apache.spark.scheduler.Task.run(Task.scala:89)at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:213)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)at java.lang.Thread.run(Thread.java:745)Driver stacktrace:at org.apache.spark.scheduler.DAGScheduler.org$apache$spark$scheduler$DAGScheduler$$failJobAndIndependentStages(DAGScheduler.scala:1431)at org.apache.spark.scheduler.DAGScheduler$$anonfun$abortStage$1.apply(DAGScheduler.scala:1419)at org.apache.spark.scheduler.DAGScheduler$$anonfun$abortStage$1.apply(DAGScheduler.scala:1418)at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59)at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:47)at org.apache.spark.scheduler.DAGScheduler.abortStage(DAGScheduler.scala:1418)at org.apache.spark.scheduler.DAGScheduler$$anonfun$handleTaskSetFailed$1.apply(DAGScheduler.scala:799)at org.apache.spark.scheduler.DAGScheduler$$anonfun$handleTaskSetFailed$1.apply(DAGScheduler.scala:799)at scala.Option.foreach(Option.scala:236)at org.apache.spark.scheduler.DAGScheduler.handleTaskSetFailed(DAGScheduler.scala:799)at org.apache.spark.scheduler.DAGSchedulerEventProcessLoop.doOnReceive(DAGScheduler.scala:1640)......Caused by: java.lang.ClassNotFoundException: com.spark.firstApp.HelloSpark$$anonfun$2at java.net.URLClassLoader.findClass(URLClassLoader.java:381)at java.lang.ClassLoader.loadClass(ClassLoader.java:424)at java.lang.ClassLoader.loadClass(ClassLoader.java:357)at java.lang.Class.forName0(Native Method)at java.lang.Class.forName(Class.java:348)at org.apache.spark.serializer.JavaDeserializationStream$$anon$1.resolveClass(JavaSerializer.scala:68)at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1613)at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)......16/02/23 16:39:53 INFO SparkContext: Invoking stop() from shutdown hook16/02/23 16:39:53 INFO SparkUI: Stopped Spark web UI at :404016/02/23 16:39:53 INFO SparkDeploySchedulerBackend: Shutting down all executors......Process finished with exit code 1这个问题我解决了,在设置SparkConf()的时候,需要把本机生成的JAR包路径进行制定,如:val conf = new SparkConf().setAppName("SogouResult").setMaster("spark://master:7077").setJars(List("D:\\IDEA workspace\\helloSpark\\out\\artifacts\\helloSpark_jar\\helloSpark.jar"))

如何处理Scala未来中抛出的异常

Spark也是基于JVM,我们构筑分布式系统,借助JVM,而不一定是Java语言。 Spark和消息中间件KAFKA等都是用Scala编写的,学好Scala是掌握Spark的关键。Scala基础语法入门实战首先,参照相关攻略,在Linux下分别下载安装Java、Scala,然后配置Java和Scala环境变量。安装完毕,在终端敲入scala即可进入Scala命令行,如下所示:root@Master:~# scalaWelcome to Scala version 2.10.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_66).Type in expressions to have them evaluated.Type :help for more information.简单测试scala》 1+2res0: Int = 3scala》 1.5*2res1: Double = 3.0scala》 3*res1res2: Double = 9.0//按Tab键,命令自动补全scala》 res2.to toByte toChar toDouble toFloat toInt toLong toShort toString变量var声明可变变量;val声明不可变变量。val声明的不可变变量,不希望数据被改变,RDD内部的数据都是不可变,所以在Spark中一般都是使用val。//下面声明了一个不可变变量result,result的值不可改变。scala》 val result=2+10result: Int = 12//假若修改result的值,会提示出错,如下:scala》 result=13《console》:8: error: reassignment to valresult=13//var声明可变变量:scala》 var name="Spark"name: String = Sparkscala》 name="Scala" //可以修改变量name的值name: String = Scalascala》 name //name的值现在为Scalares4: String = Scala//val声明不可变变量//age被声明为Int类型的不可变变量scala》 val age: Int=0age: Int = 0//声明为String类型scala》 val name:String=nullname: String = null一行代码声明多个变量scala》 val age1,age2,age3=0age1: Int = 0age2: Int = 0age3: Int = 0基本数据类型的自动转换操作Scala自己可以完成基本数据类型的自动转换操作。//输入整数10,按Tab键盘,可以看见它本身的很多方法:scala》 10.totoByte toChar toDouble toFloat toInt toLong toShort toStringscala》 10.toStringres5: String = 10scala》 0.to(5)res6: scala.collection.immutable.Range.Inclusive = Range(0, 1, 2, 3, 4, 5)给了我们一个不可变的集合,获得的结果是:0~5,所以Scala一切皆对象!Scala隐私转换:当类型本身没有没有这个方法,但是又需要调用这个方法时,内部就会自动触发隐式转换。刚才的示例中,Int本身没有to这样的方法,Scala引擎内部会隐式自动转换成RichInt,就像上面0.to(5)这样的调用,RichInt对象类型才有to这样的函数。scala》 1+1res7: Int = 2//因为Scala一切皆对象,所以以上示例又可以写成:scala》 1.+(1)res9: Double = 2.0这个示例,内部其实就是Int的一个隐式转换,+是类的一个方法。Scala没有++、---操作运算:scala》 var age=10age: Int = 10// Scala没有++、---操作运算scala》 age++《console》:9: error: value ++ is not a member of Intage++^//但是++运算可以用下面方式实现:scala》 age +=1scala》 ageres12: Int = 11求最大、最小值scala》 min(20,4)《console》:8: error: not found: value minmin(20,4)^该示例因为没有导入库,所以出错。scala》 import scala.math._ //导入math库import scala.math._scala》 min(20,4)res14: Int = 4apply工厂构造实现方法在Spark中,大量的实例的构造都是使用了apply方式。scala》 Array(1,2,3,4)res15: Array = Array(1, 2, 3, 4)scala》 val array=Array(1,2,3,4)array: Array = Array(1, 2, 3, 4)//array是一个声明整数类型的数组变量, 其实内部是自动调用了Array.apply方法,等同如下:scala》 val array = Array.apply(1,2,3,4)array: Array = Array(1, 2, 3, 4)条件控制、循环// if表达式示例:scala》 if(age》=18) "成年人" else "小孩"res16: String = 成年人scala》 val result=if(age》=18) "成年人" else "小孩"result: String = 成年人scala》 resultres17: String = 成年人scala》 val result = if(age》=18){| "adult"| buffered=10| buffered| }以上一个代码块,代码块后面有个返回值buffered,代码块的返回值就是最后一行的值。 打印值scala》 println("Spark") //输出一行字符串并换行Sparkscala》 println("\nSpark") //换行,输出一行字符串再换行。\n是换行转义符。Sparkscala》 print("Spark") //输出一行字符串,不换行Sparkscala》填充占位符scala》 printf("%s是大数据框架的未来", "Spark") //%s是占位符Spark是大数据框架的未来读取内容readLine用于读取输入的内容scala》 readLine //此时敲入Scala之后,然后回车res28: String = Scalascala》 res28res29: String = Scala补充说明,readLine是一个方法,如果方法如果没有参数,那么可以不带括号,readLine()跟readLine效果一样。循环//声明一个可变变量,初始值为100scala》 var element=100 element: Int = 100//while循环示例:scala》 while(element》90){| println(element)| element -= 1| }100999897969594939291scala》 0 to elementres32: scala.collection.immutable.Range.Inclusive = Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90)//for循环遍历并打印scala》 for(i《-80 to element) println(i) 8081828384858687888990//循环并增加条件判断scala》 for(i《-0 to element if i%2==0) print(i+" ") 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90//for循环,并break退出scala》 import scala.util.control.Breaks._ //添加break引用import scala.util.control.Breaks._scala》 for(i《-1 to 10){| if(i==4) break| println(i)| }123scala.util.control.BreakControl//循环,并returnscala》 val n=5n: Int = 5scala》 def f1:Any = {| for(i 《-1 to 10){| if(i==n) return i| println(i)| }| }f1: Anyscala》 f11234res1: Any = 5解释以上代码块,def是定义一个函数。f1就是一个函数。二、 Scala函数入门实战函数示例函数的定义使用def关键字,并且函数体最后有返回值。//声明了一个函数f3,两个参数:param1是String类型,param2为Int类型。param2默认值为30,因为有了默认值,那么在调用上可以不传param2。scala》 def f3(param1:String, param2:Int=30) = param1 + param2 f3: (param1: String, param2: Int)String//调用函数f3,传入第一个参数param1值为Spark,没有传入第二个参数,默认为30。scala》 f3("Spark") res4: String = Spark30//带名参数调用,即在函数调用时,显示指定参数名,并不按顺序传入。scala》 f3(param2=100, param1="Scala")res5: String = Scala100//变长参数, 定义了一个sum函数,参数numbers是变成参数,即传入的Int变量个数不定。在函数体中,对传入的全部Int变量进行循环遍历并累计求和,最后把结果返回。scala》 def sum(numbers: Int*)={var result=0; for(element《-numbers) result +=element; result}sum: (numbers: Int*)Intscala》 sum(1,2,3,4,5,6,7,8,9,10)res1: Int = 55//下面示例是一个非常经典的语法scala》 sum(1 to 10: _*) // _* 表示提取里面的每个元素, 然后作为变长参数传递res3: Int = 55过程没有返回值的函数就是过程。//这是一个函数scala》 def morning(content:String) = "Good" + contentmorning: (content: String)String//这是一个过程scala》 def morning(content:String) { println( "Good" + content)}morning: (content: String)Unit//强制声明一个过程scala》 def morning(content:String):Unit = "Good" + contentmorning: (content: String)Unit声明lazy类型scala》 import scala.io.Source._ //导入引用库import scala.io.Source._//声明一个lazy类型的变量content,打开一个不存在的文件。scala》 lazy val content = fromFile("/root/txt")content: scala.io.BufferedSource = 《lazy》以上示例执行不会出错,表明content变量并没有执行。//如果去掉lazy关键字,那么会出错,提示文件不存在。scala》 val content = fromFile("/root/txt")java.io.FileNotFoundException: /root/txt (No such file or directory)at java.io.FileInputStream.open0(Native Method)at java.io.FileInputStream.open(FileInputStream.java:195)at java.io.FileInputStream.《init》(FileInputStream.java:138)耗时的操作,在大型分布式系统中,比较常见。声明lazy类型的变量,在需要的时候才去执行。异常//首先导入相关引用包scala》 import java.io._import java.io._scala》//示例打开一个存在的文件,使用try…catch捕获异常scala》 try{| val content = fromFile("/root/.bashrc").mkString| }catch{| //case是一个偏函数| case _: FileNotFoundException =》 println("Oh, file not found!")| }finally{| println("Ok!")| }Ok!scala》//示例打开一个不存在的文件,使用try…catch捕获异常scala》 try{| val content = fromFile("/root/.bashrc111").mkString| }catch{| //case是一个偏函数| case _: FileNotFoundException =》 println("Oh, file not found!")| }finally{| println("Ok!")| }Oh, file not found!Ok!三、 Scala中Array、Map、Tuple实战Array//声明变量arr为Array整数类型的数组,包含5个元素。scala》 val arr= new Array(5)arr: Array = Array(0, 0, 0, 0, 0)//访问第三个元素scala》 arr(2)res15: Int = 0//修改第三个元素scala》 arr(2)=8//再次查看arr数组,发现第三个元素值已经变成8了。scala》 arrres17: Array = Array(0, 0, 8, 0, 0)补充说明,刚才声明arr数组变量时,所以把它声明为val不可变变量,这只是表明arr的地址不可以变,但是数组里面的元素还是可以变化的。//在Spark中,更常见地创建数组是直接通过类名scala》 val arr1 = Array("Scala", "Spark")arr1: Array = Array(Scala, Spark)该示例中,声明arr1为数组变量时,没有使用new关键字,也没有指定String类型,系统默认根据元素值,自动推导出元素的类型为String。没有使用new关键字,其实它内部调用了apply方法, apply是工厂类构造器。等同于下面的写法:scala》 val arr1 = Array.apply("Scala", "Spark")arr1: Array = Array(Scala, Spark)//给Array增加元素。下面写法会出错,给arr1数组增加一个元素,比如:scala》 arr1(2)="Hadoop"java.lang.ArrayIndexOutOfBoundsException: 2at .《init》(《console》:16)at .《clinit》(《console》)……如果需要给Array增加元素,那么此时就应该使用ArrayBuffer类型。ArrayBuffer//首先导入库scala》 import scala.collection.mutable.ArrayBufferimport scala.collection.mutable.ArrayBuffer//定义一个ArrayBuffer类型的变量arrbufferscala》 val arrbuffer=ArrayBuffer()arrbuffer: scala.collection.mutable.ArrayBuffer = ArrayBuffer()//向arrbuffer中增加一个元素,值为10scala》 arrbuffer += 10res23: arrbuffer.type = ArrayBuffer(10)//向arrbuffer中增加多个元素scala》 arrbuffer += (11,1,3,5)res25: arrbuffer.type = ArrayBuffer(10, 11, 1, 3, 5)//查看arrbuffer的内容scala》 arrbufferres26: scala.collection.mutable.ArrayBuffer = ArrayBuffer(10, 11, 1, 3, 5)//向arrbuffer中增加一个数组scala》 arrbuffer ++= Array(1,2,3,4)res27: arrbuffer.type = ArrayBuffer(10, 11, 1, 3, 5, 1, 2, 3, 4)//截掉arrbuffer后面的3个元素scala》 arrbuffer.trimEnd(3)//再次查看arrbuffer的内容,发现元素:2, 3, 4被截掉scala》 arrbufferres29: scala.collection.mutable.ArrayBuffer = ArrayBuffer(10, 11, 1, 3, 5, 1)//在第5个位置,插入元素值100scala》 arrbuffer.insert(5,100)//查看arrbuffer的内容scala》 arrbufferres32: scala.collection.mutable.ArrayBuffer = ArrayBuffer(10, 11, 1, 3, 5, 100, 1)//在第2个位置,插入多个元素:200,300,400scala》 arrbuffer.insert(2,200,300,400)//查看arrbuffer的内容scala》 arrbufferres34: scala.collection.mutable.ArrayBuffer = ArrayBuffer(10, 11, 200, 300, 400, 1, 3, 5, 100, 1)//从arrbuffer中移除第3个位置上的元素scala》 arrbuffer.remove(3)res35: Int = 300 //被移除的值是300//再次查看arrbuffer的内容,发现第3个位置上的元素300不见了。scala》 arrbufferres36: scala.collection.mutable.ArrayBuffer = ArrayBuffer(10, 11, 200, 400, 1, 3, 5, 100, 1)//从arrbuffer中移除第2个位置开始的,3个元素,即:200, 400, 1scala》 arrbuffer.remove(2,3)//再次查看arrbuffer的内容,发现三个元素:200, 400, 1 不见了。scala》 arrbufferres38: scala.collection.mutable.ArrayBuffer = ArrayBuffer(10, 11, 3, 5, 100, 1)//可变数组变成不可变数组,此时arr2是一个不可变数组scala》 val arr2 = arrbuffer.toArrayarr2: Array = Array(10, 11, 3, 5, 100, 1)// Array.toBuffer的结果变成一个ArrayBufferscala》 arr2.toBufferres40: scala.collection.mutable.Buffer = ArrayBuffer(10, 11, 3, 5, 100, 1)//遍历一个数组:scala》 for(elem 《- arr2) println(elem)1011351001//遍历数组时加上条件scala》 arr2res42: Array = Array(10, 11, 3, 5, 100, 1)//遍历时的条件,跳过偶数位上的元素scala》 for(i 《- 0 until (arr2.length, 2)) println(arr2(i))103100此时打印出来的结果,跳过了元素:11、5、1//从尾部开始遍历scala》 for(i 《- (0 until arr2.length).reverse) println(arr2(i))1100531110//对数组进行排序//导入排序包scala》 import scala.util.Sortingimport scala.util.Sortin

面向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) : Unit =  {    val ted = Person( Ted Neward )  }}

  case 类本身可能并不比传统类有趣 或者有多么的与众不同 但是在使用它们时会有一个很重要的差别 与引用等式相比 case 类生成的代码更喜欢按位(biise)等式 因此下面的代码对 Java 程序员来说有些有趣的惊喜

   清单 这不是以前的类

   object App{  def main(args : Array) : 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) : 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  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计算1到100的和(编写一个函数,返回3个数中最大的两个数的和.)

本文编辑:admin

本文相关文章:


cesium的datasource(Cesium快速上手9-Camera和Scene中的其他函数使用)

cesium的datasource(Cesium快速上手9-Camera和Scene中的其他函数使用)

大家好,关于cesium的datasource很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于Cesium快速上手9-Camera和Scene中的其他函数使用的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您

2024年9月9日 18:01

day函数是什么意思(函数DAY($A$3)*4-4 代表什么意思)

day函数是什么意思(函数DAY($A$3)*4-4 代表什么意思)

各位老铁们好,相信很多人对day函数是什么意思都不是特别的了解,因此呢,今天就来为大家分享下关于day函数是什么意思以及函数DAY($A$3)*4-4 代表什么意思的问题知识,还望可以帮助大家,解决大家的一些困惑,下面一起来看看吧!本文目录

2024年9月8日 10:45

递归算法解决八皇后问题(用递归函数设计八皇后问题的回溯算法C++代码)

递归算法解决八皇后问题(用递归函数设计八皇后问题的回溯算法C++代码)

大家好,如果您还对递归算法解决八皇后问题不太了解,没有关系,今天就由本站为大家分享递归算法解决八皇后问题的知识,包括用递归函数设计八皇后问题的回溯算法C++代码的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!本文目录用递归

2024年9月8日 09:01

result函数(matlab中Result函数什么意思)

result函数(matlab中Result函数什么意思)

大家好,今天小编来为大家解答以下的问题,关于result函数,matlab中Result函数什么意思这个很多人还不知道,现在让我们一起来看看吧!本文目录matlab中Result函数什么意思mysql_store_result的函数原型c语

2024年9月8日 07:15

c语言lseek函数的用法(问一个关于lseek函数的效率问题)

c语言lseek函数的用法(问一个关于lseek函数的效率问题)

这篇文章给大家聊聊关于c语言lseek函数的用法,以及问一个关于lseek函数的效率问题对应的知识点,希望对各位有所帮助,不要忘了收藏本站哦。本文目录问一个关于lseek函数的效率问题C语言,更改指定位置数据文件内容,求大神c语言实现文件内

2024年9月7日 14:45

字符串长度不同怎样取(怎样用EXCEL函数选长度不一样的字符串如A14-1208-01与A14D-1208-01要选的字符分别是A14-1208与A14D-1208)

字符串长度不同怎样取(怎样用EXCEL函数选长度不一样的字符串如A14-1208-01与A14D-1208-01要选的字符分别是A14-1208与A14D-1208)

本篇文章给大家谈谈字符串长度不同怎样取,以及怎样用EXCEL函数选长度不一样的字符串如A14-1208-01与A14D-1208-01要选的字符分别是A14-1208与A14D-1208对应的知识点,文章可能有点长,但是希望大家可以阅读完,

2024年9月7日 08:30

指数函数图像怎么画(指数函数的图象如何画)

指数函数图像怎么画(指数函数的图象如何画)

各位老铁们,大家好,今天由我来为大家分享指数函数图像怎么画,以及指数函数的图象如何画的相关问题知识,希望对大家有所帮助。如果可以帮助到大家,还望关注收藏下本站,您的支持是我们最大的动力,谢谢大家了哈,下面我们开始吧!本文目录指数函数的图象如

2024年9月6日 18:05

概率密度函数和分布函数(如何区别概率密度函数和分布函数)

概率密度函数和分布函数(如何区别概率密度函数和分布函数)

“概率密度函数和分布函数”相关信息最新大全有哪些,这是大家都非常关心的,接下来就一起看看概率密度函数和分布函数(如何区别概率密度函数和分布函数)!本文目录如何区别概率密度函数和分布函数概率密度函数与分布函数有什么区别和联系概率密度函数和分布

2024年9月6日 10:20

python递归函数考试题(python题目:要求用递归、递推和Lambda三种方式编写power(n,x)函数)

python递归函数考试题(python题目:要求用递归、递推和Lambda三种方式编写power(n,x)函数)

本篇文章给大家谈谈python递归函数考试题,以及python题目:要求用递归、递推和Lambda三种方式编写power(n,x)函数对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解

2024年9月6日 03:40

if函数按日期判断取值(EXCEL中if函数日期的判断)

if函数按日期判断取值(EXCEL中if函数日期的判断)

这篇文章给大家聊聊关于if函数按日期判断取值,以及EXCEL中if函数日期的判断对应的知识点,希望对各位有所帮助,不要忘了收藏本站哦。本文目录EXCEL中if函数日期的判断如何用excel的IF函数来判定日期晚于某一天以及晚几天如何使用ex

2024年9月5日 05:35

c语言中函数abs 和 fabs有什么区别?C语言中fabs表示什么意思

c语言中函数abs 和 fabs有什么区别?C语言中fabs表示什么意思

各位老铁们好,相信很多人对fabs都不是特别的了解,因此呢,今天就来为大家分享下关于fabs以及c语言中函数abs 和 fabs有什么区别的问题知识,还望可以帮助大家,解决大家的一些困惑,下面一起来看看吧!本文目录c语言中函数abs 和 f

2024年9月4日 08:10

高一数学三角函数全部公式(高一数学所有关于三角函数的公式)

高一数学三角函数全部公式(高一数学所有关于三角函数的公式)

大家好,今天小编来为大家解答以下的问题,关于高一数学三角函数全部公式,高一数学所有关于三角函数的公式这个很多人还不知道,现在让我们一起来看看吧!本文目录高一数学所有关于三角函数的公式高一数学三角函数基本公式高一数学三角函数公式、高中三角函数

2024年9月3日 04:00

绝对值函数求最值(带绝对值的多元函数求最值)

绝对值函数求最值(带绝对值的多元函数求最值)

大家好,今天小编来为大家解答以下的问题,关于绝对值函数求最值,带绝对值的多元函数求最值这个很多人还不知道,现在让我们一起来看看吧!本文目录带绝对值的多元函数求最值绝对值不等式怎么求最大值最小值,比如求绝对值的几何意义求最值怎么求绝对值最大值

2024年9月2日 23:45

matlab求隐函数导数(使用matlab进行隐函数求解)

matlab求隐函数导数(使用matlab进行隐函数求解)

大家好,今天小编来为大家解答以下的问题,关于matlab求隐函数导数,使用matlab进行隐函数求解这个很多人还不知道,现在让我们一起来看看吧!本文目录使用matlab进行隐函数求解怎么用matlab求解复杂的隐函数如何用matlab对隐函

2024年9月2日 07:00

幂函数比较大小总结(幂函数比较大小的方法)

幂函数比较大小总结(幂函数比较大小的方法)

大家好,幂函数比较大小总结相信很多的网友都不是很明白,包括幂函数比较大小的方法也是一样,不过没有关系,接下来就来为大家分享关于幂函数比较大小总结和幂函数比较大小的方法的一些知识点,大家可以关注收藏,免得下次来找不到哦,下面我们开始吧!本文目

2024年9月1日 09:10

matlablength函数用法(如何使用MATLAB作出如下函数ns关于x变化的函数,x的取值范围为0到10)

matlablength函数用法(如何使用MATLAB作出如下函数ns关于x变化的函数,x的取值范围为0到10)

大家好,如果您还对matlablength函数用法不太了解,没有关系,今天就由本站为大家分享matlablength函数用法的知识,包括如何使用MATLAB作出如下函数ns关于x变化的函数,x的取值范围为0到10的问题都会给大家分析到,还望

2024年9月1日 04:40

php截取字符串以特定的字符分割(PHP怎么用substr函数截取字符串中的某部分)

php截取字符串以特定的字符分割(PHP怎么用substr函数截取字符串中的某部分)

大家好,关于php截取字符串以特定的字符分割很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于PHP怎么用substr函数截取字符串中的某部分的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还望关注下

2024年9月1日 03:45

small函数相反的函数(excel中small函数有什么作用)

small函数相反的函数(excel中small函数有什么作用)

这篇文章给大家聊聊关于small函数相反的函数,以及excel中small函数有什么作用对应的知识点,希望对各位有所帮助,不要忘了收藏本站哦。本文目录excel中small函数有什么作用excel small函数怎么用excel数组公式,S

2024年9月1日 01:40

easyx安装教程(【C语言】如何在VC++6.0中使用TC2.0特有的函数呢)

easyx安装教程(【C语言】如何在VC++6.0中使用TC2.0特有的函数呢)

各位老铁们好,相信很多人对easyx安装教程都不是特别的了解,因此呢,今天就来为大家分享下关于easyx安装教程以及【C语言】如何在VC++6.0中使用TC2.0特有的函数呢的问题知识,还望可以帮助大家,解决大家的一些困惑,下面一起来看看吧

2024年8月31日 06:40

js中构造函数的作用(js构造函数和普通函数的区别)

js中构造函数的作用(js构造函数和普通函数的区别)

“js中构造函数的作用”相关信息最新大全有哪些,这是大家都非常关心的,接下来就一起看看js中构造函数的作用(js构造函数和普通函数的区别)!本文目录js构造函数和普通函数的区别JS构造函数到底如何理解js中new Function 创建函数

2024年8月30日 19:45

更多文章:


oracle下载时候会有plsql吗(安装完oracle后怎么用pl sql)

oracle下载时候会有plsql吗(安装完oracle后怎么用pl sql)

本文目录安装完oracle后怎么用pl sqlOracle 安装并安装plsql 问题oracle客户端是plsql吗安装了oracle还需要安装plsql吗装了oracle客户端才有sqlplus吗安装完oracle后怎么用pl sql1

2024年6月27日 22:54

进度管理软件有哪些(自动生成进度计划的软件)

进度管理软件有哪些(自动生成进度计划的软件)

“进度管理软件有哪些”相关信息最新大全有哪些,这是大家都非常关心的,接下来就一起看看进度管理软件有哪些(自动生成进度计划的软件)!本文目录自动生成进度计划的软件进度计划软件哪个好用工程项目进度管理软件有什么求推荐工程项目进度管理软件可以帮助

2024年9月6日 00:05

java程序设计和c语言(关于JAVA语言,和C语言有什么联系吗)

java程序设计和c语言(关于JAVA语言,和C语言有什么联系吗)

大家好,今天小编来为大家解答以下的问题,关于java程序设计和c语言,关于JAVA语言,和C语言有什么联系吗这个很多人还不知道,现在让我们一起来看看吧!本文目录关于JAVA语言,和C语言有什么联系吗Java程序设计跟C语言程序设计有什么区别

2024年8月20日 12:55

为什么不允许个人做论坛(给域名备案论坛为什么个人不可以啊)

为什么不允许个人做论坛(给域名备案论坛为什么个人不可以啊)

本文目录给域名备案论坛为什么个人不可以啊现在如果个人做论坛性质的网站并且按规定来(不知道有没有),国家是不禁止的对吧有个人备案号,能做论坛吗国内为什么不允许个人办论坛形式的网站以个人身份可以建论坛类网站吗有什么依据个人做论坛的问题,网站备案

2024年3月23日 20:25

eclipse没有jsp选项怎么办(eclipse创建JSP时没有这个选项)

eclipse没有jsp选项怎么办(eclipse创建JSP时没有这个选项)

大家好,如果您还对eclipse没有jsp选项怎么办不太了解,没有关系,今天就由本站为大家分享eclipse没有jsp选项怎么办的知识,包括eclipse创建JSP时没有这个选项的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始

2024年6月30日 01:44

钉钉小游戏代码(钉钉的隐藏游戏代码是什么)

钉钉小游戏代码(钉钉的隐藏游戏代码是什么)

大家好,今天小编来为大家解答以下的问题,关于钉钉小游戏代码,钉钉的隐藏游戏代码是什么这个很多人还不知道,现在让我们一起来看看吧!本文目录钉钉的隐藏游戏代码是什么爱坤钉钉小游戏代码是什么免费在钉钉里玩戏的代码是什么在钉钉玩mc游戏代码平板上钉

2024年8月4日 19:35

token下载app(app怎样防止token被盗取)

token下载app(app怎样防止token被盗取)

本文目录app怎样防止token被盗取为什么 APP 要用 token 而不用拼多多小程序和app账号token一样吗token什么意思 前端如何使用tokentoken钱包app 前景app怎样防止token被盗取token是个凭条,不过

2024年7月3日 00:17

parents是什么意思(parents是什么意思)

parents是什么意思(parents是什么意思)

本文目录parents是什么意思parents是什么意思中文翻译parents的中文是什么意思parents是什么意思英语Parents 的中文是什么呢parents的意思parents是什么意思啊parents是什么意思“parents”

2024年6月26日 02:54

霹雳七大神秘分别都是什么(霹雳侠影之创神篇简介红冕七元)

霹雳七大神秘分别都是什么(霹雳侠影之创神篇简介红冕七元)

“霹雳七大神秘分别都是什么”相关信息最新大全有哪些,这是大家都非常关心的,接下来就一起看看霹雳七大神秘分别都是什么(霹雳侠影之创神篇简介红冕七元)!本文目录霹雳侠影之创神篇简介红冕七元谁能告诉我霹雳戏的主要人物的名字(最好有简介)霹雳中的不

2024年8月25日 06:55

双向链表排序(C#取List的前几条数据)

双向链表排序(C#取List的前几条数据)

本文目录C#取List的前几条数据双向循环链表建立前驱和建立后继先后顺序C语言 双向链表 快速排序求高手做个c语言设计一个双向链表的排序这是个关于SCAN算法的c语言描述,程序无错,运行有错双向链表排序c语言程序设计用c++语言实现双向链表

2024年7月22日 04:53

marrakech课文分段(marrakech六个场景分析)

marrakech课文分段(marrakech六个场景分析)

本文目录marrakech六个场景分析高级英语第二册marrakech的16,17段用了什么修辞手法课文marrakech的写作原则有哪些高级英语的其它版本marrakech课文缩写george orwell的marrakech的主旨是什么

2024年7月9日 22:12

arm是什么软件(ARM是硬件还是软件)

arm是什么软件(ARM是硬件还是软件)

本文目录ARM是硬件还是软件arm什么意思arm是什么意思 什么是ARM1.ARM编译器是一款什么样的软件 2.ARM产品线包含哪些产品 3.ARM代理商目前有哪些arm是什么意思ARM到底是什么的缩写ARM是硬件还是软件指一种处理器的架构

2024年7月24日 05:39

数据库专业就业前景(大数据专业就业前景如何)

数据库专业就业前景(大数据专业就业前景如何)

本文目录大数据专业就业前景如何大数据专业主要学什么 就业方向及前景分析大数据专业就业前景如何前景比较好。大数据人才紧缺,未来发展空间广阔。大数据产业是一个人才短缺、一个巨大的搏厅市场需求。现在的大数据产业只有五十万人,而这个行业的整体需求却

2024年5月17日 23:20

巴啦啦小魔仙蔡徐坤在哪一集(12年前巴啦啦小魔仙,谁注意到跑龙套的小演员)

巴啦啦小魔仙蔡徐坤在哪一集(12年前巴啦啦小魔仙,谁注意到跑龙套的小演员)

各位老铁们,大家好,今天由我来为大家分享巴啦啦小魔仙蔡徐坤在哪一集,以及12年前巴啦啦小魔仙,谁注意到跑龙套的小演员的相关问题知识,希望对大家有所帮助。如果可以帮助到大家,还望关注收藏下本站,您的支持是我们最大的动力,谢谢大家了哈,下面我们

2024年7月10日 13:30

sorting翻译(请问sorting or routing number是什么意思)

sorting翻译(请问sorting or routing number是什么意思)

本文目录请问sorting or routing number是什么意思括号里sorting blockbustwrs from turkeys怎么翻译请问sorting or routing number是什么意思你不用在意中文意思,so

2024年5月3日 02:59

007无暇赴死豆瓣(无暇赴死影评)

007无暇赴死豆瓣(无暇赴死影评)

本文目录无暇赴死影评《007无暇赴死》海外票房大卖,剧中有哪些细思极恐的细节重磅大片《007:无暇赴死》票房破1亿美元,这部剧的口碑如何电影007:无暇赴死剧情简介《007:无暇赴死》彩蛋有没有无暇赴死影评《007:无暇赴死》是007系列电

2024年7月21日 17:56

cpa广告联盟平台(网络cpa和广告联盟是一样的吗)

cpa广告联盟平台(网络cpa和广告联盟是一样的吗)

本文目录网络cpa和广告联盟是一样的吗介绍几个CPA注册类广告联盟,cpa交友联盟是啥广告联盟中的CPL和CPA分别是什么cpa001这个联盟怎样网络cpa和广告联盟是一样的吗网络cpa和广告联盟,这是两个内容的东西。网络cpa 说的是cp

2024年7月3日 16:58

在线电子书转换器(电子书怎样在线转换成azw3)

在线电子书转换器(电子书怎样在线转换成azw3)

本文目录电子书怎样在线转换成azw3为什么电子书在线转换不了epub如何把 mobi 格式的电子书转换成 PDF电子书怎么在线转换成EPUB格式怎样在线把电子书格式转为Word文件为什么电子书在线转换不了TXT怎样把电子书文件在线转为TXT

2024年5月18日 17:24

签到表怎么制作表格(员工签到表格怎么做)

签到表怎么制作表格(员工签到表格怎么做)

本文目录员工签到表格怎么做wps怎么做签到表格Excel表格怎么制作签到表吃饭签到表格怎么做怎么用word制作签到表怎样用word做会议签到表EXCEL表格想做一个签到表,表头左上角处想用斜线分开单元格,填上日期和姓名怎么做啊员工签到表格怎

2024年7月16日 12:10

phpthinkphp接口验证(thinkphp 验证码问题)

phpthinkphp接口验证(thinkphp 验证码问题)

本文目录thinkphp 验证码问题为什么thinkphp自带的验证码功能,验证码输错一次后,再输对,也一直报ThinkPHP 自动验证是怎么弄得thinkphp3.2.1怎么验证验证码Thinkphp3.2.3接入公众号响应微信发送的To

2024年7月4日 12:09

近期文章

本站热文

iphone vpn设置(ios设置vpn快捷开关)
2024-07-22 15:01:12 浏览:2334
windows12正式版下载(操作系统Windows Server 2012 R2,在哪能下载到,公司用的)
2024-07-20 17:26:53 浏览:1730
java安装教程(win10如何安装JAVA)
2024-07-19 19:55:49 浏览:1156
client mfc application未响应(每次进cf就提示client MFC Application未响应该怎么办啊!急急急)
2024-07-20 11:15:58 浏览:1152
标签列表

热门搜索