摘要:差異代表一個結果的兩個可能性,一個是,一個是代表可選擇的值,一個是代表有值,一個是值為空常用于結果可能為的情況運算的結果有兩種情況,一個是運行正常,即,一個是運行出錯,拋出異常,即,其中里面包含的是異常的信息共同點三者都存在兩種可能性的值都
差異
Either
代表一個結果的兩個可能性,一個是 Right ,一個是 Left
Option
代表可選擇的值,一個是 Some(代表有值),一個是 None (值為空);常用于結果可能為 null 的情況;
Try
運算的結果有兩種情況,一個是運行正常,即 Success ,一個是運行出錯,拋出異常 ,即 Failure ,其中 Failure 里面包含的是異常的信息;
共同點
三者都存在兩種可能性的值;都可以在結果之上進行 map 、 flatMap 等操作;
Either
Right 和 Left 是繼承自 Either 的兩個 case 類;
//Left final case class Left[+A, +B](@deprecatedName("a, "2.12.0") value: A) extends Either[A, B] //Right final case class Right[+A, +B](@deprecatedName("b, "2.12.0") value: B) extends Either[A, B]
Eihter 代表一個結果的兩個可能性,一個是 Right ,一個是 Left ;
import scala.io.StdIn._ val in = readLine("Type Either a string or an Int: ") val result: Either[String,Int] = try Right(in.toInt) catch { case e: NumberFormatException => Left(in) } result match { case Right(x) => s"You passed me the Int: $x, which I will increment. $x + 1 = ${x+1}" case Left(x) => s"You passed me the String: $x" }
Either 是偏向 Right 值的,在 Either 使用 map 、flatMap 等操作時,只有 Either 的結果是 Right 時,才會觸發(fā)操作;習慣性地將Left 值代表不好的結果(失敗的結果),Right 代表好的結果(成功的結果);
def doubled(i: Int) = i * 2 Right(42).map(doubled) // Right(84) Left(42).map(doubled) // Left(42)
由于Either 定義了 flatMap 和 map ,所以可以對 Either 使用 for comprehensions;
val right1 = Right(1) : Right[Double, Int] //確定right1的類型 val right2 = Right(2) val right3 = Right(3) val left23 = Left(23.0) : Left[Double, Int] //確定left23的類型 val left42 = Left(42.0) for { x <- right1 y <- right2 z <- right3 } yield x + y + z // Right(6) for { x <- right1 y <- right2 z <- left23 } yield x + y + z // Left(23.0) for { x <- right1 y <- left23 z <- right2 } yield x + y + z // Left(23.0)
但是不支持使用守衛(wèi)表達式
for { i <- right1 if i > 0 } yield i // error: value withFilter is not a member of Right[Double,Int]
同樣,下面也是不支持的
for (x: Int <- right1) yield x // error: value withFilter is not a member of Right[Double,Int]
由于 for comprehensions 使用 map 和 flatMap ,所以必須要推導參數的類型,并且該類型必須是 Either ;特別的地方在于,由于Either 是偏向Right 的,所以是對于Either的值為Left必須要指定其類型,否則,該位置的默認類型為Nothing;
for { x <- left23 y <- right1 z <- left42 // type at this position: Either[Double, Nothing] } yield x + y + z // ^ // error: ambiguous reference to overloaded definition, // both method + in class Int of type (x: Char)Int // and method + in class Int of type (x: Byte)Int // match argument types (Nothing) for (x <- right2 ; y <- left23) yield x + y // Left(23.0) for (x <- right2 ; y <- left42) yield x + y // error for { x <- right1 y <- left42 // type at this position: Either[Double, Nothing] z <- left23 } yield x + y + z // Left(42.0), but unexpectedly a `Either[Double,String]`
Option
Some 和 None 是繼承自 Option 的兩個 case 類;
//Some final case class Some[+A](@deprecatedName("x, "2.12.0") value: A) extends Option[A] //None case object None extends Option[Nothing]
對Option 的習慣用法是把它當作集合或者monad ,通過map 、flatMap 、filter 和 foreach :
//方式一 val name: Option[String] = request getParameter "name" val upper = name map { _.trim } filter { _.length != 0 } map { _.toUpperCase } println(upper getOrElse "") //方式一等價于方式二 val upper = for { name <- request getParameter "name" //由于For表達式的作用,如何此處返回None,那么整個表達式將返回None trimmed <- Some(name.trim) upper <- Some(trimmed.toUpperCase) if trimmed.length != 0 } yield upper println(upper getOrElse "")
另外一個習慣用法是(不太推薦)通過模式匹配:
val nameMaybe = request getParameter "name" nameMaybe match { case Some(name) => println(name.trim.toUppercase) case None => println("No name value") }
Try
Failure 和 Success 是繼承自 Try 的兩個 case 類;
//Failure final case class Failure[+T](exception: Throwable) extends Try[T] //Success final case class Success[+T](value: T) extends Try[T]
Try 常用于那些存在異常的地方,通過Try 不用確定地對可能出現的異常進行處理;
import scala.io.StdIn import scala.util.{Try, Success, Failure} def divide: Try[Int] = { val dividend = Try(StdIn.readLine("Enter an Int that you"d like to divide: ").toInt) val divisor = Try(StdIn.readLine("Enter an Int that you"d like to divide by: ").toInt) val problem = dividend.flatMap(x => divisor.map(y => x/y)) problem match { case Success(v) => println("Result of " + dividend.get + "/"+ divisor.get +" is: " + v) Success(v) case Failure(e) => println("You must"ve divided by zero or entered something that"s not an Int. Try again!") println("Info from the exception: " + e.getMessage) divide } }
在上面的例子中,可以看出 Try 的一個重要的特性,就是Try 具有管道的功能 ,flatMap 和 map 將那些成功完成的操作的結果包裝成Success ,將那些異常包裝成 Failure ,而對于 recover 和 recoverWith 則是默認對 Failure 結果進行觸發(fā);
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/71147.html
摘要:復制代碼報錯信息如下錯誤錯誤解答執(zhí)行命令安裝依賴包。為了讓讀者理解問題,重現上述錯誤過程,命令如下復制代碼1、Nginx安裝過程報錯錯誤一:軟件依賴包未正確安裝問題---PCRE依賴包沒有安裝 ./configure: error: the HTTP rewrite module requires the PCRE library. You can either disable the...
摘要:在深入理解中的變量上中我們看到的引入,使得可以很方便地在多線程環(huán)境中使用局部變量。特別需要注意的是,基類的并不會屏蔽派生類中的創(chuàng)建。到此,整個源碼核心部分已經理解的差不多了,只剩下用來執(zhí)行清除工作。 在 深入理解Python中的ThreadLocal變量(上) 中我們看到 ThreadLocal 的引入,使得可以很方便地在多線程環(huán)境中使用局部變量。如此美妙的功能到底是怎樣實現的?如果你...
摘要:在中也可以看到執(zhí)行記錄,包括錯誤信息解讀生命周期在任務開始之前即在初始化之后執(zhí)行任何或實現之前創(chuàng)建一個記錄記錄開始事件的條目,此事件由觸發(fā),來向系統(tǒng)指出所有都可以使用。在加載完成所有的之后,任務執(zhí)行并更新數據庫中的執(zhí)行結果和狀態(tài),最后退出。 起步:什么是 spring cloud task Spring Cloud Task makes it easy to create short ...
摘要:源碼漫游二描述在一中其實已經把作為的框架中數據流相關跑了一遍??瓷厦鎯膳殴卜椒ㄟ@個方法的調用在整個源碼中就兩處,和。過程,這也是導致我們在源碼運行中總是看見在有無函數分支,的時候總是能看見函數,然后就進入對組件。 Vue2 源碼漫游(二) 描述: 在(一)中其實已經把Vue作為MVVM的框架中數據流相關跑了一遍。這一章我們先看mount這一步,這樣Vue大的主線就基本跑通了。...
閱讀 2267·2023-04-25 14:50
閱讀 1256·2021-10-13 09:50
閱讀 1868·2019-08-30 15:56
閱讀 1847·2019-08-29 15:29
閱讀 2891·2019-08-29 15:27
閱讀 3551·2019-08-29 15:14
閱讀 1198·2019-08-29 13:01
閱讀 3303·2019-08-26 14:06