導航:首頁 > 源碼編譯 > 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版相關的資料

熱點內容
虐殺原形1壓縮 瀏覽:201
如何去掉安卓系統的通知 瀏覽:1001
解壓好的游戲如何打開 瀏覽:508
微商輔助app哪個最好 瀏覽:943
為什麼用雲伺服器下載東西那麼快 瀏覽:786
java數據結構和演算法視頻教程 瀏覽:120
java上傳多個文件 瀏覽:166
php搭建工具 瀏覽:307
安卓怎麼下載百度外來應用 瀏覽:62
什麼app可以查看全國疫情數據 瀏覽:823
python反編譯工具 瀏覽:222
qt演算法模擬 瀏覽:360
查看uuid的命令 瀏覽:50
強光抑制演算法 瀏覽:14
u盤加密後能拷貝嗎 瀏覽:889
asus帶命令提示的安全模式 瀏覽:1004
php截取字元串指定 瀏覽:248
lxe加密視頻怎麼設置 瀏覽:607
php數組刪除第一個元素 瀏覽:167
安卓指示器怎麼使用 瀏覽:572