<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # [X分鐘速成Y](http://learnxinyminutes.com/) ## 其中 Y=Scala 源代碼下載:?[learnscala-zh.scala](http://learnxinyminutes.com/docs/files/learnscala-zh.scala) Scala - 一門可拓展的語言 ~~~ /* 自行設置: 1) 下載 Scala - http://www.scala-lang.org/downloads 2) unzip/untar 到您喜歡的地方,并把 bin 子目錄添加到 path 環境變量 3) 在終端輸入 scala,啟動 Scala 的 REPL,您會看到提示符: scala> 這就是所謂的 REPL (讀取-求值-輸出循環,英語: Read-Eval-Print Loop), 您可以在其中輸入合法的表達式,結果會被打印。 在教程中我們會進一步解釋 Scala 文件是怎樣的,但現在先了解一點基礎。 */ ///////////////////////////////////////////////// // 1\. 基礎 ///////////////////////////////////////////////// // 單行注釋開始于兩個斜杠 /* 多行注釋,如您之前所見,看起來像這樣 */ // 打印并強制換行 println("Hello world!") println(10) // 沒有強制換行的打印 print("Hello world") // 通過 var 或者 val 來聲明變量 // val 聲明是不可變的,var 聲明是可修改的。不可變性是好事。 val x = 10 // x 現在是 10 x = 20 // 錯誤: 對 val 聲明的變量重新賦值 var y = 10 y = 20 // y 現在是 20 /* Scala 是靜態語言,但注意上面的聲明方式,我們沒有指定類型。 這是因為類型推導的語言特性。大多數情況, Scala 編譯器可以推測變量的類型, 所以您不需要每次都輸入。可以像這樣明確聲明變量類型: */ val z: Int = 10 val a: Double = 1.0 // 注意從 Int 到 Double 的自動轉型,結果是 10.0, 不是 10 val b: Double = 10 // 布爾值 true false // 布爾操作 !true // false !false // true true == false // false 10 > 5 // true // 數學運算像平常一樣 1 + 1 // 2 2 - 1 // 1 5 * 3 // 15 6 / 2 // 3 6 / 4 // 1 6.0 / 4 // 1.5 // 在 REPL 計算一個表達式會返回給您結果的類型和值 1 + 7 /* 上行的結果是: scala> 1 + 7 res29: Int = 8 這意味著計算 1 + 7 的結果是一個 Int 類型的對象,其值為 8 注意 "res29" 是一個連續生成的變量名,用以存儲您輸入的表達式結果, 您看到的輸出可能不一樣。 */ "Scala strings are surrounded by double quotes" 'a' // Scala 的字符 // '不存在單引號字符串' <= 這會導致錯誤 // String 有常見的 Java 字符串方法 "hello world".length "hello world".substring(2, 6) "hello world".replace("C", "3") // 也有一些額外的 Scala 方法,另請參見:scala.collection.immutable.StringOps "hello world".take(5) "hello world".drop(5) // 字符串改寫:留意前綴 "s" val n = 45 s"We have $n apples" // => "We have 45 apples" // 在要改寫的字符串中使用表達式也是可以的 val a = Array(11, 9, 6) s"My second daughter is ${a(0) - a(2)} years old." // => "My second daughter is 5 years old." s"We have double the amount of ${n / 2.0} in apples." // => "We have double the amount of 22.5 in apples." s"Power of 2: ${math.pow(2, 2)}" // => "Power of 2: 4" // 添加 "f" 前綴對要改寫的字符串進行格式化 f"Power of 5: ${math.pow(5, 2)}%1.0f" // "Power of 5: 25" f"Square root of 122: ${math.sqrt(122)}%1.4f" // "Square root of 122: 11.0454" // 未處理的字符串,忽略特殊字符。 raw"New line feed: \n. Carriage return: \r." // => "New line feed: \n. Carriage return: \r." // 一些字符需要轉義,比如字符串中的雙引號 "They stood outside the \"Rose and Crown\"" // => "They stood outside the "Rose and Crown"" // 三個雙引號可以使字符串跨越多行,并包含引號 val html = """<form id="daform"> <p>Press belo', Joe</p> <input type="submit"> </form>""" ///////////////////////////////////////////////// // 2\. 函數 ///////////////////////////////////////////////// // 函數可以這樣定義: // // def functionName(args...): ReturnType = { body... } // // 如果您以前學習過傳統的編程語言,注意 return 關鍵字的省略。 // 在 Scala 中, 函數代碼塊最后一條表達式就是返回值。 def sumOfSquares(x: Int, y: Int): Int = { val x2 = x * x val y2 = y * y x2 + y2 } // 如果函數體是單行表達式,{ } 可以省略: def sumOfSquaresShort(x: Int, y: Int): Int = x * x + y * y // 函數調用的語法是熟知的: sumOfSquares(3, 4) // => 25 // 在多數情況下 (遞歸函數是需要注意的例外), 函數返回值可以省略, // 變量所用的類型推導一樣會應用到函數返回值中: def sq(x: Int) = x * x // 編譯器會推斷得知返回值是 Int // 函數可以有默認參數 def addWithDefault(x: Int, y: Int = 5) = x + y addWithDefault(1, 2) // => 3 addWithDefault(1) // => 6 // 匿名函數是這樣的: (x:Int) => x * x // 和 def 不同,如果語義清晰,匿名函數的參數類型也可以省略。 // 類型 "Int => Int" 意味著這個函數接收一個 Int 并返回一個 Int。 val sq: Int => Int = x => x * x // 匿名函數的調用也是類似的: sq(10) // => 100 // 如果您的匿名函數中每個參數僅使用一次, // Scala 提供一個更簡潔的方式來定義他們。這樣的匿名函數極為常見, // 在數據結構部分會明顯可見。 val addOne: Int => Int = _ + 1 val weirdSum: (Int, Int) => Int = (_ * 2 + _ * 3) addOne(5) // => 6 weirdSum(2, 4) // => 16 // return 關鍵字是存在的,但它只從最里面包裹了 return 的 def 函數中返回。 // 警告: 在 Scala 中使用 return 容易出錯,應該避免使用。 // 在匿名函數中沒有效果,例如: def foo(x: Int): Int = { val anonFunc: Int => Int = { z => if (z > 5) return z // 這一行令 z 成為 foo 函數的返回值! else z + 2 // 這一行是 anonFunc 函數的返回值 } anonFunc(x) // 這一行是 foo 函數的返回值 } /* * 譯者注:此處是指匿名函數中的 return z 成為最后執行的語句, * 在 anonFunc(x) 下面的表達式(假設存在)不再執行。如果 anonFunc * 是用 def 定義的函數, return z 僅返回到 anonFunc(x) , * 在 anonFunc(x) 下面的表達式(假設存在)會繼續執行。 */ ///////////////////////////////////////////////// // 3\. 控制語句 ///////////////////////////////////////////////// 1 to 5 val r = 1 to 5 r.foreach( println ) r foreach println // 附注: Scala 對點和括號的要求想當寬松,注意其規則是不同的。 // 這有助于寫出讀起來像英語的 DSL(領域特定語言) 和 API(應用編程接口)。 (5 to 1 by -1) foreach ( println ) // while 循環 var i = 0 while (i < 10) { println("i " + i); i+=1 } while (i < 10) { println("i " + i); i+=1 } // 沒錯,再執行一次,發生了什么?為什么? i // 顯示 i 的值。注意 while 是經典的循環方式,它連續執行并改變循環中的變量。 // while 執行很快,比 Java 的循環快,但像上面所看到的那樣用組合子和推導式 // 更易于理解和并行化。 // do while 循環 do { println("x is still less than 10"); x += 1 } while (x < 10) // Scala 中尾遞歸是一種符合語言習慣的遞歸方式。 // 遞歸函數需要清晰的返回類型,編譯器不能推斷得知。 // 這是一個 Unit。 def showNumbersInRange(a:Int, b:Int):Unit = { print(a) if (a < b) showNumbersInRange(a + 1, b) } showNumbersInRange(1,14) // 條件語句 val x = 10 if (x == 1) println("yeah") if (x == 10) println("yeah") if (x == 11) println("yeah") if (x == 11) println ("yeah") else println("nay") println(if (x == 10) "yeah" else "nope") val text = if (x == 10) "yeah" else "nope" ///////////////////////////////////////////////// // 4\. 數據結構 ///////////////////////////////////////////////// val a = Array(1, 2, 3, 5, 8, 13) a(0) a(3) a(21) // 拋出異常 val m = Map("fork" -> "tenedor", "spoon" -> "cuchara", "knife" -> "cuchillo") m("fork") m("spoon") m("bottle") // 拋出異常 val safeM = m.withDefaultValue("no lo se") safeM("bottle") val s = Set(1, 3, 7) s(0) s(1) /* 這里查看 map 的文檔 - * http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Map * 并確保你會閱讀 */ // 元組 (1, 2) (4, 3, 2) (1, 2, "three") (a, 2, "three") // 為什么有這個? val divideInts = (x:Int, y:Int) => (x / y, x % y) divideInts(10,3) // 函數 divideInts 同時返回結果和余數 // 要讀取元組的元素,使用 _._n,n是從1開始的元素索引 val d = divideInts(10,3) d._1 d._2 ///////////////////////////////////////////////// // 5\. 面向對象編程 ///////////////////////////////////////////////// /* 旁白: 教程中到現在為止我們所做的一切只是簡單的表達式(值,函數等)。 這些表達式可以輸入到命令行解釋器中作為快速測試,但它們不能獨立存在于 Scala 文件。舉個例子,您不能在 Scala 文件上簡單的寫上 "val x = 5"。相反 Scala 文件 允許的頂級結構是: - objects - classes - case classes - traits 現在來解釋這些是什么。 */ // 類和其他語言的類相似,構造器參數在類名后聲明,初始化在類結構體中完成。 class Dog(br: String) { // 構造器代碼在此 var breed: String = br // 定義名為 bark 的方法,返回字符串 def bark = "Woof, woof!" // 值和方法作用域假定為 public。"protected" 和 "private" 關鍵字也是可用的。 private def sleep(hours: Int) = println(s"I'm sleeping for $hours hours") // 抽象方法是沒有方法體的方法。如果取消下面那行注釋,Dog 類必須被聲明為 abstract // abstract class Dog(...) { ... } // def chaseAfter(what: String): String } val mydog = new Dog("greyhound") println(mydog.breed) // => "greyhound" println(mydog.bark) // => "Woof, woof!" // "object" 關鍵字創造一種類型和該類型的單例。 // Scala 的 class 常常也含有一個 “伴生對象”,class 中包含每個實例的行為,所有實例 // 共用的行為則放入 object 中。兩者的區別和其他語言中類方法和靜態方法類似。 // 請注意 object 和 class 可以同名。 object Dog { def allKnownBreeds = List("pitbull", "shepherd", "retriever") def createDog(breed: String) = new Dog(breed) } // Case 類是有額外內建功能的類。Scala 初學者常遇到的問題之一便是何時用類 // 和何時用 case 類。界線比較模糊,但通常類傾向于封裝,多態和行為。類中的值 // 的作用域一般為 private , 只有方向是暴露的。case 類的主要目的是放置不可變 // 數據。它們通常只有幾個方法,且方法幾乎沒有副作用。 case class Person(name: String, phoneNumber: String) // 創造新實例,注意 case 類不需要使用 "new" 關鍵字 val george = Person("George", "1234") val kate = Person("Kate", "4567") // 使用 case 類,您可以輕松得到一些功能,像 getters: george.phoneNumber // => "1234" // 每個字段的相等性比較(無需覆蓋 .equals) Person("George", "1234") == Person("Kate", "1236") // => false // 簡單的拷貝方式 // otherGeorge == Person("george", "9876") val otherGeorge = george.copy(phoneNumber = "9876") // 還有很多。case 類同時可以用于模式匹配,接下來會看到。 // 敬請期待 Traits ! ///////////////////////////////////////////////// // 6\. 模式匹配 ///////////////////////////////////////////////// // 模式匹配是一個強大和常用的 Scala 特性。這是用模式匹配一個 case 類的例子。 // 附注:不像其他語言, Scala 的 case 不需要 break, 其他語言中 switch 語句的 // fall-through 現象不會發生。 def matchPerson(person: Person): String = person match { // Then you specify the patterns: case Person("George", number) => "We found George! His number is " + number case Person("Kate", number) => "We found Kate! Her number is " + number case Person(name, number) => "We matched someone : " + name + ", phone : " + number } val email = "(.*)@(.*)".r // 定義下一個例子會用到的正則 // 模式匹配看起來和 C語言家族的 switch 語句相似,但更為強大。 // Scala 中您可以匹配很多東西: def matchEverything(obj: Any): String = obj match { // 匹配值: case "Hello world" => "Got the string Hello world" // 匹配類型: case x: Double => "Got a Double: " + x // 匹配時指定條件 case x: Int if x > 10000 => "Got a pretty big number!" // 像之前一樣匹配 case 類: case Person(name, number) => s"Got contact info for $name!" // 匹配正則表達式: case email(name, domain) => s"Got email address $name@$domain" // 匹配元組: case (a: Int, b: Double, c: String) => s"Got a tuple: $a, $b, $c" // 匹配數據結構: case List(1, b, c) => s"Got a list with three elements and starts with 1: 1, $b, $c" // 模式可以嵌套 case List(List((1, 2,"YAY"))) => "Got a list of list of tuple" } // 事實上,你可以對任何有 "unapply" 方法的對象進行模式匹配。 // 這個特性如此強大以致于 Scala 允許定義一個函數作為模式匹配: val patternFunc: Person => String = { case Person("George", number) => s"George's number: $number" case Person(name, number) => s"Random person's number: $number" } ///////////////////////////////////////////////// // 7\. 函數式編程 ///////////////////////////////////////////////// // Scala 允許方法和函數作為其他方法和函數的參數和返回值。 val add10: Int => Int = _ + 10 // 一個接受一個 Int 類型參數并返回一個 Int 類型值的函數 List(1, 2, 3) map add10 // List(11, 12, 13) - add10 被應用到每一個元素 // 匿名函數可以被使用來代替有命名的函數: List(1, 2, 3) map (x => x + 10) // 如果匿名函數只有一個參數可以用下劃線作為變量 List(1, 2, 3) map (_ + 10) // 如果您所應用的匿名塊和匿名函數都接受一個參數,那么你甚至可以省略下劃線 List("Dom", "Bob", "Natalia") foreach println // 組合子 // 譯注: val sq: Int => Int = x => x * x s.map(sq) val sSquared = s. map(sq) sSquared.filter(_ < 10) sSquared.reduce (_+_) // filter 函數接受一個 predicate (函數根據條件 A 返回 Boolean)并選擇 // 所有滿足 predicate 的元素 List(1, 2, 3) filter (_ > 2) // List(3) case class Person(name:String, age:Int) List( Person(name = "Dom", age = 23), Person(name = "Bob", age = 30) ).filter(_.age > 25) // List(Person("Bob", 30)) // Scala 的 foreach 方法定義在某些集合中,接受一個函數并返回 Unit (void 方法) // 另請參見: // http://www.scala-lang.org/api/current/index.html#scala.collection.IterableLike@foreach(f:A=>Unit):Unit val aListOfNumbers = List(1, 2, 3, 4, 10, 20, 100) aListOfNumbers foreach (x => println(x)) aListOfNumbers foreach println // For 推導式 for { n <- s } yield sq(n) val nSquared2 = for { n <- s } yield sq(n) for { n <- nSquared2 if n < 10 } yield n for { n <- s; nSquared = n * n if nSquared < 10} yield nSquared /* 注意,這些不是 for 循環,for 循環的語義是‘重復’,然而 for 推導式定義 兩個數據集合的關系。 */ ///////////////////////////////////////////////// // 8\. 隱式轉換 ///////////////////////////////////////////////// /* 警告 警告: 隱式轉換是 Scala 中一套強大的特性,因此容易被濫用。 * Scala 初學者在理解它們的工作原理和最佳實踐之前,應抵制使用它的誘惑。 * 我們加入這一章節僅因為它們在 Scala 的庫中太過常見,導致沒有用隱式轉換的庫 * 就不可能做有意義的事情。這章節主要讓你理解和使用隱式轉換,而不是自己聲明。 */ // 可以通過 "implicit" 聲明任何值(val, 函數,對象等)為隱式值, // 請注意這些例子中,我們用到第5部分的 Dog 類。 implicit val myImplicitInt = 100 implicit def myImplicitFunction(breed: String) = new Dog("Golden " + breed) // implicit 關鍵字本身不改變值的行為,所以上面的值可以照常使用。 myImplicitInt + 2 // => 102 myImplicitFunction("Pitbull").breed // => "Golden Pitbull" // 區別在于,當另一段代碼“需要”隱式值時,這些值現在有資格作為隱式值。 // 一種情況是隱式函數參數。 def sendGreetings(toWhom: String)(implicit howMany: Int) = s"Hello $toWhom, $howMany blessings to you and yours!" // 如果提供值給 “howMany”,函數正常運行 sendGreetings("John")(1000) // => "Hello John, 1000 blessings to you and yours!" // 如果省略隱式參數,會傳一個和參數類型相同的隱式值, // 在這個例子中, 是 “myImplicitInt": sendGreetings("Jane") // => "Hello Jane, 100 blessings to you and yours!" // 隱式的函數參數使我們可以模擬其他函數式語言的 type 類(type classes)。 // 它經常被用到所以有特定的簡寫。這兩行代碼是一樣的: def foo[T](implicit c: C[T]) = ... def foo[T : C] = ... // 編譯器尋找隱式值另一種情況是你調用方法時 // obj.method(...) // 但 "obj" 沒有一個名為 "method" 的方法。這樣的話,如果有一個參數類型為 A // 返回值類型為 B 的隱式轉換,obj 的類型是 A,B 有一個方法叫 "method" ,這樣 // 轉換就會被應用。所以作用域里有上面的 myImplicitFunction, 我們可以這樣做: "Retriever".breed // => "Golden Retriever" "Sheperd".bark // => "Woof, woof!" // 這里字符串先被上面的函數轉換為 Dog 對象,然后調用相應的方法。 // 這是相當強大的特性,但再次提醒,請勿輕率使用。 // 事實上,當你定義上面的隱式函數時,編譯器會作出警告,除非你真的了解 // 你正在做什么否則不要使用。 ///////////////////////////////////////////////// // 9\. 雜項 ///////////////////////////////////////////////// // 導入類 import scala.collection.immutable.List // 導入所有子包 import scala.collection.immutable._ // 一條語句導入多個類 import scala.collection.immutable.{List, Map} // 使用 ‘=>’ 對導入進行重命名 import scala.collection.immutable.{ List => ImmutableList } // 導入所有類,排除其中一些。下面的語句排除了 Map 和 Set: import scala.collection.immutable.{Map => _, Set => _, _} // 在 Scala 文件用 object 和單一的 main 方法定義程序入口: object Application { def main(args: Array[String]): Unit = { // stuff goes here. } } // 文件可以包含多個 class 和 object,用 scalac 編譯源文件 // 輸入和輸出 // 按行讀文件 import scala.io.Source for(line <- Source.fromFile("myfile.txt").getLines()) println(line) // 用 Java 的 PrintWriter 寫文件 val writer = new PrintWriter("myfile.txt") writer.write("Writing line for line" + util.Properties.lineSeparator) writer.write("Another line here" + util.Properties.lineSeparator) writer.close() ~~~ ## 更多的資源 [為沒耐心的人準備的 Scala](http://horstmann.com/scala/) [Twitter Scala school](http://twitter.github.io/scala_school/) [The Scala documentation](http://www.scala-lang.org/documentation/) [在瀏覽器嘗試 Scala](http://scalatutorials.com/tour/) 加入?[Scala 用戶組](https://groups.google.com/forum/#!forum/scala-user)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看