เหตุใดจึงใช้ข้อยกเว้นเกิน (ทำเครื่องหมาย)


17

เมื่อไม่นานมานี้ฉันเริ่มใช้ Scala แทน Java ส่วนหนึ่งของกระบวนการ "แปลง" ระหว่างภาษาสำหรับฉันได้เรียนรู้การใช้งานEitherอัตโนมัติแทน (ตรวจสอบ) Exceptions ฉันได้รับการเข้ารหัสด้วยวิธีนี้มาระยะหนึ่งแล้ว แต่เมื่อไม่นานมานี้ฉันเริ่มสงสัยว่าเป็นวิธีที่ดีกว่าหรือไม่

ข้อEitherได้เปรียบที่สำคัญอย่างหนึ่งที่มากกว่าExceptionคือประสิทธิภาพที่ดีกว่า Exceptionความต้องการที่จะสร้างสแต็คร่องรอยและจะถูกโยน เท่าที่ฉันเข้าใจการขว้างปาExceptionไม่ใช่ส่วนที่เรียกร้อง แต่การสร้างสแต็กติดตามคือ

แต่แล้วหนึ่งสามารถสร้าง / สืบทอดExceptions พร้อมด้วยscala.util.control.NoStackTraceและมากยิ่งขึ้นดังนั้นผมเห็นความอุดมสมบูรณ์ของกรณีที่ด้านซ้ายของEitherในความเป็นจริงException(ละทิ้งการเพิ่มประสิทธิภาพการทำงาน)

ข้อดีอีกข้อหนึ่งEitherก็คือคอมไพเลอร์ - ความปลอดภัย คอมไพเลอร์ Scala จะไม่บ่นเกี่ยวกับExceptions ที่ไม่ได้จัดการ(ต่างจากคอมไพเลอร์ของ Java) แต่ถ้าฉันไม่เข้าใจผิดการตัดสินใจครั้งนี้มีเหตุผลด้วยเหตุผลเดียวกับที่กำลังคุยกันในหัวข้อนี้ดังนั้น ...

ในแง่ของไวยากรณ์ฉันรู้สึกว่าExceptionสไตล์นั้นชัดเจนกว่า ตรวจสอบบล็อคโค้ดต่อไปนี้ (ทั้งการใช้ฟังก์ชันเดียวกัน):

Either รูปแบบ:

def compute(): Either[String, Int] = {

    val aEither: Either[String, String] = if (someCondition) Right("good") else Left("bad")

    val bEithers: Iterable[Either[String, Int]] = someSeq.map {
        item => if (someCondition(item)) Right(item.toInt) else Left("bad")
    }

    for {
        a <- aEither.right
        bs <- reduce(bEithers).right
        ignore <- validate(bs).right
    } yield compute(a, bs)
}

def reduce[A,B](eithers: Iterable[Either[A,B]]): Either[A, Iterable[B]] = ??? // utility code

def validate(bs: Iterable[Int]): Either[String, Unit] = if (bs.sum > 22) Left("bad") else Right()

def compute(a: String, bs: Iterable[Int]): Int = ???

Exception รูปแบบ:

@throws(classOf[ComputationException])
def compute(): Int = {

    val a = if (someCondition) "good" else throw new ComputationException("bad")
    val bs = someSeq.map {
        item => if (someCondition(item)) item.toInt else throw new ComputationException("bad")
    }

    if (bs.sum > 22) throw new ComputationException("bad")

    compute(a, bs)
}

def compute(a: String, bs: Iterable[Int]): Int = ???

หลังดูดีกว่าสำหรับฉันมากและโค้ดที่จัดการกับความล้มเหลว (ทั้งการจับคู่รูปแบบEitherหรือtry-catch) นั้นค่อนข้างชัดเจนทั้งสองกรณี

ดังนั้นคำถามของฉันคือ - ทำไมใช้Eitherเกิน (ตรวจสอบ) Exception?

ปรับปรุง

หลังจากอ่านคำตอบแล้วฉันก็ตระหนักว่าฉันอาจไม่ได้นำเสนอแก่นแท้ของภาวะที่กลืนไม่เข้าคายไม่ออกของฉัน ความกังวลของฉันไม่ได้อยู่กับการขาดtry-catch; หนึ่งสามารถ "จับ" ซึ่งเป็นExceptionที่มีTryหรือใช้เพื่อตัดข้อยกเว้นด้วยcatchLeft

ปัญหาหลักของฉันกับEither/ Tryมาเมื่อฉันเขียนรหัสที่อาจล้มเหลวในหลายจุดตลอดทาง; ในสถานการณ์เหล่านี้เมื่อพบความล้มเหลวฉันต้องเผยแพร่ความล้มเหลวนั้นตลอดทั้งรหัสของฉันดังนั้นจึงทำให้โค้ดมีความยุ่งยากมากขึ้น (ดังแสดงในตัวอย่างที่กล่าวมา)

จริงๆแล้วมีวิธีทำลายรหัสโดยไม่ใช้Exceptions อีกอันreturn(อันที่จริงแล้วเป็นอีก "taboo" ใน Scala) รหัสจะยังคงชัดเจนกว่าEitherวิธีการและในขณะที่เป็นบิตสะอาดน้อยกว่าExceptionรูปแบบจะมีความกลัวของการไม่จับไม่มีExceptions

def compute(): Either[String, Int] = {

  val a = if (someCondition) "good" else return Left("bad")

  val bs: Iterable[Int] = someSeq.map {
    item => if (someCondition(item)) item.toInt else return Left("bad")
  }

  if (bs.sum > 22) return Left("bad")

  val c = computeC(bs).rightOrReturn(return _)

  Right(computeAll(a, bs, c))
}

def computeC(bs: Iterable[Int]): Either[String, Int] = ???

def computeAll(a: String, bs: Iterable[Int], c: Int): Int = ???

implicit class ConvertEither[L, R](either: Either[L, R]) {

  def rightOrReturn(f: (Left[L, R]) => R): R = either match {
    case Right(r) => r
    case Left(l) => f(Left(l))
  }
}

โดยพื้นฐานแล้วการreturn Leftแทนที่throw new ExceptionและวิธีการโดยปริยายบนrightOrReturn, เป็นส่วนเสริมสำหรับการเผยแพร่ข้อยกเว้นอัตโนมัติขึ้นสแต็ก


อ่านสิ่งนี้: mauricio.github.io/2014/02/17/…
Robert Harvey

@RobertHarvey Tryดูเหมือนว่าส่วนใหญ่กล่าวถึงในบทความ ส่วนเกี่ยวกับEithervs Exceptionเพียงระบุว่าEithers ควรใช้เมื่อกรณีอื่น ๆ ของวิธีการคือ "ไม่พิเศษ" ก่อนอื่นนี่เป็นคำนิยามที่ชัดเจนมาก ๆ ประการที่สองมันคุ้มค่ากับการลงโทษไวยากรณ์หรือไม่ ฉันหมายความว่าฉันไม่รังเกียจที่จะใช้Eithers ถ้ามันไม่ได้อยู่เหนือไวยากรณ์ที่พวกเขามีอยู่
Eyal Roth

Eitherดูเหมือนว่า monad สำหรับฉัน ใช้มันเมื่อคุณต้องการผลประโยชน์การจัดองค์ประกอบการทำงานที่ monads จัดหาให้ หรืออาจจะไม่ได้
Robert Harvey

2
@ RobertHarvey: เทคนิคการพูดEitherด้วยตัวเองไม่ใช่ monad การฉายภาพทั้งด้านซ้ายหรือด้านขวาเป็นภาพเดียว แต่Eitherโดยตัวมันเองไม่ได้ คุณสามารถทำให้มันเป็น monad ได้โดย "biasing" ไปทางซ้ายหรือทางขวา Eitherแต่แล้วคุณบอกความหมายบางอย่างในทั้งสองด้านของ สกาลาEitherเดิมทีไม่ฝักใฝ่ฝ่ายใด แต่ค่อนข้างเอนเอียงเมื่อเร็ว ๆ นี้ดังนั้นในปัจจุบันความจริงแล้วมันคือ monad แต่ "monadness" ไม่ใช่สมบัติโดยธรรมชาติของEitherมัน แต่เป็นผลมาจากการลำเอียง
Jörg W Mittag

@ JörgWMittag: ดีดี นั่นหมายความว่าคุณสามารถใช้มันเพื่อความดีทั้งหมดของ monadic และไม่ต้องใส่ใจเป็นพิเศษกับวิธีการ "ล้าง" รหัสผลลัพธ์ (แม้ว่าฉันสงสัยว่ารหัสความต่อเนื่องในรูปแบบการใช้งานจะสะอาดกว่ารุ่นข้อยกเว้น)
Robert Harvey

คำตอบ:


13

ถ้าคุณใช้บล็อกที่Eitherมีความจำเป็นtry-catchเท่านั้นแน่นอนว่ามันจะมีรูปแบบที่แตกต่างออกไปเพื่อทำสิ่งเดียวกัน Eithersเป็นมูลค่า พวกเขาไม่มีข้อ จำกัด เหมือนกัน คุณสามารถ:

  • หยุดพฤติกรรมของคุณในการพยายามบล็อกของคุณให้เล็กและอยู่ติดกัน ส่วน "จับ" ของEithersไม่จำเป็นต้องอยู่ถัดจากส่วน "ลอง" มันอาจถูกแชร์ในฟังก์ชั่นทั่วไป ทำให้แยกข้อกังวลออกได้ง่ายขึ้น
  • เก็บEithersในโครงสร้างข้อมูล คุณสามารถวนรอบข้อความเหล่านั้นและรวบรวมข้อความแสดงข้อผิดพลาดค้นหาข้อความแรกที่ไม่ได้ล้มเหลวประเมินพวกเขาอย่างขี้เกียจหรือคล้ายกัน
  • ขยายและปรับแต่ง ไม่ชอบต้นแบบสำเร็จรูปที่คุณต้องเขียนด้วยEithersใช่ไหม คุณสามารถเขียนฟังก์ชันตัวช่วยเพื่อให้ทำงานกับกรณีการใช้งานของคุณได้ง่ายขึ้น คุณไม่ได้ติดอยู่กับอินเทอร์เฟซเริ่มต้นที่นักออกแบบภาษาใช้

หมายเหตุสำหรับกรณีการใช้งานส่วนใหญ่ a Tryมีอินเทอร์เฟซที่เรียบง่ายกว่ามีข้อดีข้างต้นส่วนใหญ่และมักจะตรงกับความต้องการของคุณเช่นกัน An Optionนั้นง่ายกว่าหากคุณสนใจประสบความสำเร็จหรือล้มเหลวและไม่ต้องการข้อมูลสถานะใด ๆ เช่นข้อความแสดงข้อผิดพลาดเกี่ยวกับกรณีความล้มเหลว

จากประสบการณ์ของฉันEithersไม่เป็นที่ต้องการอย่างแท้จริงTrysเว้นแต่Leftจะเป็นสิ่งอื่นที่ไม่ใช่Exceptionข้อความแสดงข้อผิดพลาดในการตรวจสอบความถูกต้องและคุณต้องการรวมLeftค่าต่างๆ ตัวอย่างเช่นคุณกำลังประมวลผลอินพุตบางส่วนและคุณต้องการรวบรวมข้อความแสดงข้อผิดพลาดทั้งหมดไม่ใช่เฉพาะข้อผิดพลาดแรก สถานการณ์เหล่านั้นไม่ได้เกิดขึ้นบ่อยนักในทางปฏิบัติอย่างน้อยสำหรับฉัน

ดูเกินกว่ารุ่นลองจับแล้วคุณจะEithersพอใจกับการทำงานมากขึ้น

อัปเดต: คำถามนี้ยังคงได้รับความสนใจและฉันไม่ได้เห็นการอัปเดตของ OP ที่ทำให้คำถามเกี่ยวกับไวยากรณ์ชัดเจนขึ้นดังนั้นฉันจึงคิดว่าฉันจะเพิ่มอีก

เป็นตัวอย่างของการแยกความคิดยกเว้นนี่คือวิธีที่ฉันมักจะเขียนโค้ดตัวอย่างของคุณ:

def compute(): Either[String, Int] = {
  Right(someSeq)
    .filterOrElse(someACondition,            "someACondition failed")
    .filterOrElse(_ forall someSeqCondition, "someSeqCondition failed")
    .map(_ map {_.toInt})
    .filterOrElse(_.sum <= 22, "Sum is greater than 22")
    .map(compute("good",_))
}

ที่นี่คุณจะเห็นว่าความหมายของการfilterOrElseจับภาพสิ่งที่เรากำลังทำอยู่ในฟังก์ชั่นนี้เป็นหลัก: ตรวจสอบเงื่อนไขและเชื่อมโยงข้อความแสดงข้อผิดพลาดกับความล้มเหลวที่กำหนด เนื่องจากนี่เป็นกรณีการใช้งานทั่วไปมากfilterOrElseอยู่ในไลบรารีมาตรฐาน แต่ถ้าไม่ใช่คุณสามารถสร้างมันได้

นี่คือจุดที่บางคนมาพร้อมกับตัวอย่างเคาน์เตอร์ที่ไม่สามารถแก้ไขได้อย่างแม่นยำเหมือนกับวิธีของฉัน แต่ประเด็นที่ฉันพยายามทำคือไม่มีวิธีการใช้เพียงวิธีเดียวEithersซึ่งแตกต่างจากข้อยกเว้น มีวิธีในการลดความซับซ้อนของรหัสสำหรับสถานการณ์การจัดการข้อผิดพลาดส่วนใหญ่ถ้าคุณสำรวจฟังก์ชั่นทั้งหมดที่มีให้ใช้ด้วยEithersและเปิดให้ทดลอง


1. ความสามารถในการแยกtryและcatchเป็นอาร์กิวเมนต์ที่ยุติธรรม แต่ไม่สามารถทำได้อย่างง่ายดายด้วยTry? 2. การจัดเก็บEitherในโครงสร้างข้อมูลสามารถทำได้ควบคู่ไปกับthrowsกลไก ไม่ใช่แค่เลเยอร์พิเศษที่ด้านบนของการจัดการความล้มเหลว 3. คุณสามารถขยายExceptions แน่นอนว่าคุณไม่สามารถเปลี่ยนtry-catchโครงสร้างได้ แต่การจัดการกับความล้มเหลวเป็นเรื่องธรรมดามากที่ฉันต้องการภาษาที่จะให้หม้อไอน้ำสำหรับฉัน (ซึ่งฉันไม่ได้บังคับให้ใช้) นั่นคือการพูดว่าการทำความเข้าใจนั้นไม่ดีเพราะมันเป็นโครงสร้างสำหรับการปฏิบัติการแบบ monadic
Eyal Roth

ฉันเพิ่งตระหนักว่าคุณบอกว่าEithers สามารถขยายที่เห็นได้ชัดว่าพวกเขาไม่สามารถ (เป็นsealed traitมีเพียงสองการใช้งานทั้งสองfinal) คุณอธิบายรายละเอียดเกี่ยวกับเรื่องนี้ได้ไหม? ฉันสมมติว่าคุณไม่ได้หมายถึงความหมายที่แท้จริงของการขยาย
Eyal Roth

1
ฉันหมายถึงการขยายในคำภาษาอังกฤษไม่ใช่คำหลักการเขียนโปรแกรม การเพิ่มฟังก์ชันการทำงานโดยการสร้างฟังก์ชันเพื่อจัดการรูปแบบทั่วไป
Karl Bielefeldt

8

ทั้งสองแตกต่างกันมาก Eitherความหมายของคำนั้นกว้างกว่าเพียงเพื่อแสดงถึงความล้มเหลวในการคำนวณ

Eitherอนุญาตให้คุณส่งคืนหนึ่งในสองประเภทที่แตกต่างกัน แค่นั้นแหละ.

ตอนนี้หนึ่งในสองประเภทเหล่านี้อาจหรือไม่อาจแสดงถึงข้อผิดพลาดและอื่น ๆอาจหรือไม่อาจแสดงถึงความสำเร็จ Eitherทั่วไปมากกว่านั้นมาก Either[String, Date]คุณก็เช่นกันอาจจะมีวิธีการที่อ่านข้อมูลจากผู้ใช้ที่ได้รับอนุญาตให้ป้อนชื่อหรือวันกลับ

หรือคิดเกี่ยวกับแลมบ์ดาตัวอักษรในC♯: พวกเขาประเมินว่าเป็นFuncหรือExpressionคือพวกเขาประเมินฟังก์ชั่นที่ไม่ระบุชื่อหรือพวกเขาประเมินเป็น AST ในC♯นี้เกิดขึ้น "อย่างน่าอัศจรรย์" Either<Func<T1, T2, …, R>, Expression<T1, T2, …, R>>แต่ถ้าคุณต้องการที่จะให้ชนิดที่เหมาะสมกับมันก็จะเป็น อย่างไรก็ตามตัวเลือกทั้งสองไม่เป็นข้อผิดพลาดและตัวเลือกทั้งสองไม่เป็น "ปกติ" หรือ "พิเศษ" พวกเขาเป็นเพียงสองประเภทที่แตกต่างกันซึ่งอาจถูกส่งคืนจากฟังก์ชั่นเดียวกัน [หมายเหตุ: จริง ๆFuncต้องแยกเป็นสองกรณีเนื่องจากC♯ไม่มีUnitประเภทและดังนั้นสิ่งที่ไม่ส่งคืนสิ่งใดไม่สามารถแสดงแบบเดียวกับสิ่งที่ส่งคืนบางสิ่งได้Either<Either<Func<T1, T2, …, R>, Action<T1, T2, …>>, Expression<T1, T2, …, R>>

ตอนนี้Either สามารถใช้เพื่อแสดงประเภทความสำเร็จและประเภทความล้มเหลว และถ้าคุณเห็นด้วยกับการเรียงลำดับที่สอดคล้องกันของทั้งสองประเภทคุณสามารถมีอคติ Eitherจะชอบหนึ่งในสองประเภทนี้ซึ่งทำให้สามารถเผยแพร่ความล้มเหลวผ่านการโยงแบบ monadic แต่ในกรณีนี้คุณกำลังให้ความหมายบางอย่างกับEitherสิ่งนั้นซึ่งไม่จำเป็นต้องเป็นเจ้าของด้วยตัวเอง

Eitherที่มีหนึ่งของทั้งสองประเภทของการแก้ไขจะเป็นประเภทความผิดพลาดและจะลำเอียงไปข้างหนึ่งเพื่อเผยแพร่ข้อผิดพลาดที่มักจะเรียกว่าErrormonad และจะเป็นทางเลือกที่ดีกว่าที่จะเป็นตัวแทนของความล้มเหลวในการคำนวณที่อาจเกิดขึ้น Tryในกาลาชนิดของประเภทนี้เรียกว่า

มันทำให้รู้สึกมากขึ้นเพื่อเปรียบเทียบการใช้งานของข้อยกเว้นที่มีกว่าด้วยTryEither

ดังนั้นนี่คือเหตุผล # 1 ว่าทำไมถึงEitherอาจถูกใช้งานมากกว่าข้อยกเว้นที่ตรวจสอบแล้ว: Eitherเป็นเรื่องทั่วไปมากกว่าข้อยกเว้น สามารถใช้ในกรณีที่ไม่มีข้อยกเว้น

อย่างไรก็ตามคุณอาจถามถึงกรณีที่ถูก จำกัด ซึ่งคุณเพิ่งใช้Either(หรือมีแนวโน้มมากกว่าTry) เพื่อทดแทนข้อยกเว้น ในกรณีนี้ยังคงมีข้อดีอยู่บ้าง

ข้อได้เปรียบหลักคือคุณสามารถเลื่อนการจัดการข้อผิดพลาด คุณเพียงแค่เก็บค่าส่งคืนโดยไม่ต้องดูว่าเป็นความสำเร็จหรือข้อผิดพลาด (จัดการกับมันในภายหลัง) หรือผ่านที่อื่น (ให้คนอื่นกังวลกับมัน) รวบรวมพวกเขาในรายการ (จัดการทั้งหมดในครั้งเดียว) คุณสามารถใช้การโยงแบบ monadic เพื่อเผยแพร่พวกเขาไปตามกระบวนการประมวลผล

ความหมายของข้อยกเว้นถูกเดินสายเข้าไปในภาษา ใน Scala ข้อยกเว้นจะคลายสแต็กเช่น หากคุณปล่อยให้พวกเขาฟองขึ้นไปที่ตัวจัดการข้อยกเว้นตัวจัดการนั้นจะไม่สามารถย้อนกลับไปที่ที่มันเกิดขึ้นและแก้ไขได้ OTOH ถ้าคุณจับมันลงในสแต็กก่อนที่จะคลี่คลายและทำลายบริบทที่จำเป็นในการแก้ไขคุณอาจอยู่ในองค์ประกอบที่อยู่ในระดับต่ำเกินไปที่จะทำการตัดสินใจอย่างมีข้อมูลเกี่ยวกับวิธีดำเนินการ

นี่คือความแตกต่างในสมอลล์ทอล์คเช่นที่ข้อยกเว้นไม่ผ่อนคลายสแต็คและกลับมาทำงานต่อและคุณสามารถจับสูงยกเว้นในสแต็ค (อาจจะเป็นสูงขึ้นเป็นดีบัก) แก้ไขข้อผิดพลาด waaaaayyyyy ลงใน สแต็คและดำเนินการต่อจากที่นั่น หรือเงื่อนไข CommonLisp ที่การเพิ่มการจับและการจัดการเป็นสามสิ่งที่แตกต่างแทนสอง (การเพิ่มและการจับการจับ) เช่นเดียวกับข้อยกเว้น

การใช้ประเภทข้อผิดพลาดที่เกิดขึ้นจริงแทนที่จะเป็นข้อยกเว้นช่วยให้คุณทำสิ่งที่คล้ายกันและอื่น ๆ โดยไม่ต้องแก้ไขภาษา

แล้วมีช้างที่เห็นได้ชัดในห้อง: ข้อยกเว้นเป็นผลข้างเคียง ผลข้างเคียงเป็นสิ่งที่ชั่วร้าย หมายเหตุ: ฉันไม่ได้บอกว่านี่เป็นเรื่องจริง แต่มันเป็นมุมมองที่บางคนมีและในกรณีนั้นข้อดีของประเภทข้อผิดพลาดเหนือข้อยกเว้นนั้นชัดเจน ดังนั้นหากคุณต้องการเขียนโปรแกรมใช้งานได้คุณอาจใช้ชนิดข้อผิดพลาดด้วยเหตุผลเพียงอย่างเดียวว่าเป็นวิธีการทำงาน (โปรดทราบว่า Haskell มีข้อยกเว้นโปรดทราบว่าไม่มีใครชอบใช้มัน)


รักคำตอบ แต่ผมก็ยังไม่เห็นว่าทำไมฉันควรละเลยExceptions Eitherดูเหมือนว่าเป็นเครื่องมือที่ยอดเยี่ยม แต่ใช่ฉันถามโดยเฉพาะเกี่ยวกับการจัดการความล้มเหลวและฉันควรใช้เครื่องมือเฉพาะสำหรับงานของฉันมากกว่าเครื่องมือที่ทรงพลังทั้งหมด การชะลอความล้มเหลวในการจัดการถือเป็นข้อโต้แย้งที่ยุติธรรม แต่ใคร ๆ ก็สามารถใช้TryวิธีการโยนExceptionถ้าเขาไม่ต้องการจัดการกับมันในขณะ การติดตามสแต็กไม่ส่งผลต่อEither/ Tryเช่นกันหรือไม่ คุณอาจทำซ้ำข้อผิดพลาดเดียวกันเมื่อเผยแพร่อย่างไม่ถูกต้อง การรู้ว่าเมื่อใดที่ต้องจัดการกับความล้มเหลวนั้นไม่สำคัญในทั้งสองกรณี
Eyal Roth

และฉันไม่สามารถโต้เถียงกับการให้เหตุผล "การทำงานอย่างหมดจด" จริง ๆ ใช่ไหม?
Eyal Roth

0

สิ่งที่ดีเกี่ยวกับข้อยกเว้นคือรหัสที่มาได้จัดประเภทสถานการณ์พิเศษสำหรับคุณแล้ว ความแตกต่างระหว่างIllegalStateExceptiona และ a BadParameterExceptionนั้นง่ายกว่ามากในการแยกความแตกต่างในภาษาที่พิมพ์แข็งแกร่งกว่า หากคุณพยายามวิเคราะห์คำว่า "ดี" และ "ไม่ดี" คุณจะไม่ได้รับประโยชน์จากเครื่องมือที่ทรงพลังอย่างมากในการกำจัดนั่นคือคอมไพเลอร์ Scala ส่วนขยายของคุณเองที่Throwableสามารถรวมข้อมูลได้มากเท่าที่คุณต้องการนอกเหนือจากสตริงข้อความ

นี่คือยูทิลิตี้ที่แท้จริงของTryสภาพแวดล้อม Scala โดยThrowableทำหน้าที่เป็นเสื้อคลุมของของที่เหลือเพื่อให้ชีวิตง่ายขึ้น


2
ฉันไม่เข้าใจประเด็นของคุณ
Eyal Roth

Eitherมีปัญหาเกี่ยวกับสไตล์เนื่องจากไม่ใช่ monad จริง (?); ความเด็ดขาดของleftค่านำพาไปจากมูลค่าที่เพิ่มขึ้นเมื่อคุณใส่ข้อมูลเกี่ยวกับเงื่อนไขพิเศษในโครงสร้างที่เหมาะสม ดังนั้นการเปรียบเทียบการใช้งานEitherในกรณีหนึ่งที่ส่งคืนสตริงทางด้านซ้ายเมื่อเทียบกับtry/catchกรณีอื่นที่ใช้การพิมพ์อย่างถูกต้องThrowables นั้นไม่เหมาะสม เพราะค่าของการThrowablesให้ข้อมูลและลักษณะรวบรัดที่TryจับThrowables, Tryเป็นเดิมพันที่ดีกว่าทั้ง ... Eitherหรือtry/catch
BobDalgleish

try-catchฉันจริงไม่ได้เกี่ยวข้องเกี่ยวกับ ดังที่กล่าวไว้ในคำถามหลังดูสะอาดมากขึ้นสำหรับฉันและรหัสการจัดการความล้มเหลว
Eyal Roth
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.