导航:首页 > 源码编译 > sbt编译如何匹配scala版

sbt编译如何匹配scala版

发布时间:2022-02-11 21:13:48

① 话说模式匹配 scala里是怎么实现的

一、简单例子:

1 abstract class Expr
2 case class Var(name:String) extends Expr
3 case class Number(num:Double) extends Expr
4 case class UnOp(operator : String , arg : Expr) extends Expr
5 case class BinOp(operator : String , left : Expr , right : Expr) extends Expr
样本类:添加了case的类便是样本类。这种修饰符可以让Scala编译器自动为这个类添加一些语法上的便捷设定。如下:

添加与类名一致的工厂方法。也就是说,可以写成Var("x")来构造Var对象。
样本类参数列表中的所有参数隐式获得了val前缀,因此它被当作字段维护。
编译器为这个类添加了方法toString,hashCode和equals等方法。
模式匹配:

复制代码
1 def simplifyTop(expr : Expr) : Expr = expr match{
2 case UnOp("-" , UnOp("-" , e)) => e
3 case BinOp("+" , e , Number(0)) => e
4 case BinOp("*" , e , Number(1)) => e
5 case _ => expr
6 }
清单 15.1
复制代码
match对应java里的switch,但是写在选择器表达式之后。即: 选择器 match {备选项}。

一个模式匹配包含了一系列备选项,每个都开始于关键字case。每个备选项都包含了一个模式及一到多个表达式。箭头符号 => 隔开了模式和表达式。

match表达式通过以代码编写的先后次序尝试每个模式来完成计算。类似于UnOp("-" , UnOp("-" , e))这种形式的,是构造器模式匹配。

match与switch的比较:匹配表达式可以被看作Java风格Switch的泛化。但有三点不同:

match是Scala的表达式,始终以值作为结果;
Scala的备选项表达式永远不会“掉到”下一个case;
如果没有模式匹配,MatchError异常会被抛出。这意味着必须始终确信所有的情况都考虑到了,或者至少添加一个默认情况什么都不做。如 case _ =>
二、模式的种类

通配模式:case _ => 。表示默认的全匹配备选项。通配模式还可以用来忽略对象中不关心的部分。如:case BinOp(_,_,_) => XXX,则表示不关心二元操作符的元素是什么,只是检查是否为二元操作符

常量模式 :仅匹配自身。任何字面量都可以用作常量。包括String类型。另外,任何的val或单例对象也可以被用作常量。如,单例对象Nil是只匹配空列表的模式。

变量模式 :变量模式类似于通配符,可以匹配任何对象。不同点在于,Scala把变量绑定在匹配的对象上。之后就可以使用这个变量操作对象。如:

expr match{
case 0 => "zero"
case somethingElse => "not zero" + somethingElse
}
清单 15.6
有一个注意点:Scala使用了一个简单的文字规则来区分是一个常量还是一个变量:用小写字母开始的简单名被当作是模式变量。

构造器模式:它的存在使得模式匹配真正变得强大。它由名称及若干括号之内的模式构成。如BinOp("+" , e , Number(0))。

序列模式:可以像匹配样本类那样匹配List或Array这样的序列类型。同样的语法现在可以指定模式内任意数量的元素。如:

1 expr match{
2 case List(0 , _ , _ ) => println("found it")
3 case _ =>
4 }
清单 15.8
如果想匹配一个不指定长度的序列,可以指定_*作为模式的最后元素。它能匹配序列中0到任意数量的元素。

元组模式:例子:

复制代码
1 def tupleDemo(expr : Any) =
2 expr match {
3 case (a , b, c) => println("matched " + a + b + c)
4 case _ =>
5 }
清单 15.9
复制代码
类型模式:可以把它当做类型测试和类型转换的简易替代。例如:

复制代码
1 def generalSize(x : Any) = x match{
2 case s : String => s.length
3 case m : Map[_ , _] => m.size
4 case _ => 1
5 }
清单 15.11
复制代码
使用: scala> generalSize(Map(1 -> 'a' , 2 -> 'b'))

res15 : Int = 2

另:在Scala里类型测试和转换的代码很冗长,因为不建议这么做。

模式守卫:模式变量仅允许在模式中出现一次。如:

1 case BinOp("+" , x , x ) => BinOp("*" , x , Number(2))
这种写法就会出错。可以改成: case BinOp("+" , x , y ) if x == y => BinOp("*" , x , Number(2))

模式守卫接在模式之后,开始于if。守卫可以是任意的引用模式中变量的布尔表达式。如果存在模式守卫,那么只有在守卫返回true的时候匹配才成功。

② idea scala工程怎么找不到简单的scala工程,只有基于sbt的

创建一个Scala – sbt项目sbtFirst 虽然这个项目采用sbt格局,但少了sbt-idea插件,IDEA并不能对这个项目进行操作,只能打开sbt console。 首先我们需要修改项目的build.sbt文件,添加需要的Scala版本和libraryDependencies,注意sbt文件每行之间.

③ scala命令是怎么编译运行scala程序的

scala命令是怎么编译运行scala程序的
所以既要使用到Unicode的大的字库表,又要节省存储空间,就需要对Unicode再编码,且是根据(Unicode编码.n)内容 不定长编码 --- UTF-8是一种对(Unicode编码.n)的不定长字符编码方案。

UTF-8字符编码方案决定了(Unicode编码.n)在计算机内的存储方式。
(Unicode编码.n)经过UTF-8字符编码方案编码之后也可以看做是一个新的二进制数字,(通常用十六进制数字字符表示这个新的二进制的值,它们直接的关系是这个十六进制字符表示的值 等于 这个二进制数字的值)。

④ idea scala工程怎么找不到简单的scala工程,只有基于sbt

创建一个Scala – sbt项目sbtFirst

虽然这个项目采用sbt格局,但少了sbt-idea插件,IDEA并不能对这个项目进行操作,只能打开sbt console。

首先我们需要修改项目的build.sbt文件,添加需要的Scala版本和libraryDependencies,注意sbt文件每行之间必须有空行。

name := “sbtTest”

⑤ 如何配置sbt的build.sbt使得编译时将依赖包也打包进去

首先问题解决了,就是sbt-assembly插件的配置问题。这个文档自己前两次读表示看不懂意思。过2天又仔细看了一遍大致明白了,敢动手操作了。
assembly插件的目的是:
The goal is simple: Create a fat JAR of your project with all of its dependencies.
即将项目依赖的大文件也打包到生成的jar中。我的报错Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/spark/streaming/kafka/KafkaUtils$就是因为包含KafkaUtil的jar包没打包到jar中。
配置使用插件
下面是我的scala项目目录结构:
.
├── assembly.sbt
├── build.sbt
├── project
├── README.md
├── run-assembly.sh
├── run.sh
├── src
└── target

插件的配置取决于sbt的版本,详情见这里
我的是sbt 0.13.8,所以在project/assembly.sbt添加(assembly.sbt)要自己创建:
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.0")

配置assembly的参数
参数在项目根目录下新建assembly.sbt。
直接引入插件就可以用
sbt assembly

编译了,但是由于我的sbt下载了大量的依赖包,在编译的时候遇到了编译包冲突的问题。这个时候需要配置Merge Strategy(合并策略)

⑥ 话说模式匹配 scala里的赋值语句都是模式匹配吗

先抛个问题,下面的语句是否都合理(编译通过),哪些会引起模式匹配?

scala>vala=100
scala>valA=100
scala>vala@b=100
scala>val(a,b)=(100,200)
scala>val(a,B)=(100,200)//第二个变量大写
scala>valArray(a,b)=Array(100,200)
scala>valArray(a,B)=Array(100,200)
scala>objectTest{val2=2}
scala>objectTest{val2=3}

我们先看看其他语言(对scala有影响的)有关赋值语句的定义:

1) 在 ML 语言里,对赋值语句的定义:

val P = E

表示定义了模式P中的变量,并赋予它们表达式E中相应的值。

2) 在Erlang中等号 = 表示一个模式匹配操作

在这两种语言中,赋值语句都明确的定义为模式匹配,那么scala中,所有的赋值语句是否都是模式匹配呢?
尤其scala可以说在函数式风格上与ML(及其家族)语言有某种血缘,在这一点上是否也与ML完全一致呢?

先分析一下上面的每条赋值语句:val a = 100和val A = 100是直观且没有歧义的。

val a@b = 100是什么意思?“变量绑定模式”,当时的例子有点复杂,重新理解一下:

//给"hello"字符串对象用v1这个变量名
scala>"hello"match{casev1=>println(v1)}
//变量绑定模式,把变量v2绑定在v1这个模式上
scala>"hello"match{casev2@v1=>println(v2)}

上面的例子中,第一行中v1是个变量模式。 第二行中v2是一个新的变量,只有在v1这个模式匹配成功的情况下,才会把自己绑定到v1上,而v1因为是一个变量模式,它总能匹配成功,所以这里v2也会绑定到”hello”对象上。变量绑定模式通常不会这么使用,更多用在绑定到一个复合结构的模式上,如:

scala>List(1,List(2,3))match{caseList(_,x@List(2,_*))=>println(x.size)}


2

把变量x绑定到了嵌套的 List(2,3) 这个对象上

但赋值语句val a@b = 100跟上面的有关系么?我们通过ToolBox看看它”脱糖”后的语法树:

scala>tb.parse("vala@b=100")
res13:tb.u.Tree=
{
<synthetic>private[this]valx$3=100:@scala.uncheckedmatch{
case(a@(b@_))=>scala.Tuple2(a,b)//这一句
};
vala=x$3._1;
valb=x$3._2
}

有注释的那一句里面把a,b两个局部变量绑定到通配符”_”上,而这个通配符模式case _ =>可以匹配任何对象,所以相当于把a,b两个变量绑定到了100这个对象上,并产生了一个二元组记录这两个局部变量值。最终把二元组里的值分别赋给了我们定义的a,b两个变量。

接下来的val (a,b) = (100,200)这个赋值也容易理解,把二元组里的值分别赋给a,b两个变量么,也是经过模式匹配的么?继续用ToolBox分析:

scala>tb.parse("val(a,b)=(100,200)")
res14:tb.u.Tree=
{
<synthetic>private[this]valx$4=scala.Tuple2(100,200):@scala.uncheckedmatch{
casescala.Tuple2((a@_),(b@_))=>scala.Tuple2(a,b)
};
vala=x$4._1;
valb=x$4._2
}

看到了,是一个构造器模式与变量绑定模式的混合模式匹配。

再下一个val (a,B) = (100,200)这个与上一个有区别么?回顾一下第一篇里讲到的“常量模式”:当变量大写时将被对待为常量模式,也就是说大写B和上面的小写b是两种不同的模式!!

scala>tb.parse("val(a,B)=(100,200)")
res15:tb.u.Tree=
vala=scala.Tuple2(100,200):@scala.uncheckedmatch{
casescala.Tuple2((a@_),B)=>a
}

大写B在这里当作常量来解析,但又找不到B这个变量(除非之前有定义过),就报错了:

scala>val(a,B)=(100,200)
<console>:8:error:notfound:valueB
val(a,B)=(100,200)
^

后边两个Array的赋值语句与这两个类似,小括号写法只是元组(Tuple)的语法糖而已。

最后,真正有趣,且会让新手崩溃的情况object Test { val 2 = 2 }为什么这个编译和初始化都没问题?

scala>objectTest{val2=2}
definedmoleTest
scala>Test
res16:Test.type=Test$@3042dc22

简直逆天,难道这个背后也与模式匹配有关系么?

scala>tb.parse("objectTest{val2=2}")
res0:tb.u.Tree=
objectTestextendsscala.AnyRef{
def<init>()={
super.<init>();
()
};
<synthetic>private[this]valx$1=2:@scala.uncheckedmatch{
case2=>()
}
}

确实又是一个常量模式匹配,2匹配2,成功。

同理,下一个object Test { val 2 = 3 }也是个常量模式匹配,但为何明显不匹配,却可以编译时成功,而运行时时才报错呢?

scala>objectTest{val2=3}
definedmoleTest
scala>Test
scala.MatchError:3(ofclassjava.lang.Integer)
atTest$.<init>(<console>:8)

这是因为object 是惰性初始化的原因(lazy),如下:

//对下面的单例
objectTest{vala=2}
$scalac-Xprint:jvmA.scala
package<empty>{
objectTestextendsObject{
private[this]vala:Int=_;
<stable><accessor>defa():Int=Test.this.a;
def<init>():Test.type={
Test.super.<init>();
Test.this.a=2;//在初始化时才对成员赋值
()
}
}
}

在对多个变量赋值,或变量中有@符合,导致模式匹配还好理解,但”2=2″也引起模式匹配就会让我产生疑问:
是否所有的赋值语句都是模式匹配?

为了验证,通过编译选项查看val a=2这样对单个变量的赋值却没有看到模式匹配。
另外,如果单个变量也是模式匹配,为何大写字母val A=2没问题?假设对单个变量赋值也是模式匹配,那岂不无法定义大写的变量了;肯定是有区别的,但又怎么区分的?


在那个帖子里,martin也回复了为何val 1=2是模式匹配,并且为何不把这种情况作为错误给修复掉:

A value definition is of the form

val <pattern> = <expression> // 这个同ML和Erlang语言
1 is a <pattern>

There is one edge case:
If the pattern is a single variable (upper or lower case or backquoted), then it is always treated as a variable, not a constant. Otherwise, there would be no way to define such a value.

只有一种边缘情况:如果模式是一个单独的变量(大写、小写、或用反引号引起来的),那么它总被当作变量,而非常量。否则就没法定义这样的一个值。

所以1=2,"a"="b"这样的赋值语句虽然是一个变量,但变量名称不符合上面的约束,产生了模式匹配。至于为何不修复这个问题(直接在编译时报错),也可以从这个帖子的线索中找到原因。

linux下用sbt编译scala需要安装哪些工具

1、下载sbt通用平台压缩包:sbt-0.13.5.tgz2、建立目录,解压文件到所建立目录 $ sudo mkdir /opt/scala/sbt$ sudo tar zxvf sbt-0.13.5.tgz -C /opt/scala/3、建立启动sbt的脚本文件/*选定一个位置,建立启动sbt的脚本文本文件,如/opt/scala/s...

⑧ 使用scala 必须安装sbt吗

不需要。sbt是一个构建工具,而Scala可以直接从官网上下载到开发工具包

⑨ sbt编译时怎么匹配scala版本

build.sbt中写入:

scalaVersion := "2.10.5"

就会使用对应的版本的库进行编译

阅读全文

与sbt编译如何匹配scala版相关的资料

热点内容
js读取php返回的json 浏览:391
寻星app怎么找星星 浏览:222
磁盘要加密吗 浏览:460
夕阳风采app怎么下载不了 浏览:438
安卓方舟商店为什么不可用 浏览:638
phpecho字符串 浏览:683
中国银行app怎么关联人 浏览:755
eds是什么服务器 浏览:459
半圆命令键 浏览:446
linux文件系统实现 浏览:856
cadchange命令 浏览:328
电脑图谱源码大全 浏览:757
dos系统下命令 浏览:527
运维狗和程序员 浏览:709
哪个APP看纸牌屋 浏览:558
外卖领券app哪个最好买 浏览:315
linux中文字体包 浏览:755
git命令行建分支 浏览:850
致信服务器地址和端口要怎么找 浏览:985
android图片文件压缩 浏览:896