Or

sealed abstract class Or[+G, +B] extends Product with Serializable

Represents a value that is one of two possible types, with one type being “good” and the other “bad.”

An Or will either be a “good” value wrapped in an instance of Good or a “bad” value wrapped in an instance of Bad.

== The motivation for Or ==

Or differs from Scala's Either type in that Either treats both its Left and Right alternatives in an identical manner, whereas Or treats its two alternatives differently: it favors Good over Bad. Because of this, it is more convenient to work with Ors when you prefer one alternative over the other; for example, if one alternative represents a valid result and another represents an error.

To illustrate, imagine you want to create instances this Person class from user input strings:

case class Person(name: String, age: Int)

You might write a method that parses the name from user input string and returns an Option[String]: None if the string is empty or blank, else the trimmed string wrapped in a Some:

def parseName(input: String): Option[String] = {
 val trimmed = input.trim
 if (!trimmed.isEmpty) Some(trimmed) else None
}

You might also write a method that parses the age from user input string and returns an Option[Int]: None if either the string is not a valid integer or it is a negative integer, else the string converted to an integer wrapped in a Some:

def parseAge(input: String): Option[Int] = {
 try {
   val age = input.trim.toInt
   if (age >= 0) Some(age) else None
 }
 catch {
   case _: NumberFormatException => None
 }
}

With these building blocks you could write a method that parses name and age input strings and returns either a Person, wrapped in a Some, or None if either the name or age, or both, was invalid:

def parsePerson(inputName: String, inputAge: String): Option[Person] =
 for {
   name <- parseName(inputName)
   age <- parseAge(inputAge)
 } yield Person(name, age)

Here are some examples of invoking parsePerson:

parsePerson("Bridget Jones", "29")
// Result: Some(Person(Bridget Jones,29))

parsePerson("Bridget Jones", "")
// Result: None

parsePerson("Bridget Jones", "-29")
// Result: None

parsePerson("", "")
// Result: None

Now imagine you want to give an error message back if the user's input is invalid. You might rewrite the parsing methods to return an Either instead. In this case, the desired result is a valid name or age, which by convention should be placed on the right of the Either. The left will be a String error message. Here's the new parseName function, which returns an Either[String, String]:

def parseName(input: String): Either[String, String] = {
 val trimmed = input.trim
 if (!trimmed.isEmpty) Right(trimmed) else Left(s""""${input}" is not a valid name""")
}

And here's the new parseAge function, which returns an Either[String, Int]:

def parseAge(input: String): Either[String, Int] = {
 try {
   val age = input.trim.toInt
   if (age >= 0) Right(age) else Left(s""""${age}" is not a valid age""")
 }
 catch {
   case _: NumberFormatException => Left(s""""${input}" is not a valid integer""")
 }
}

The new parsePerson method will return an Either[String, Person]:

def parsePerson(inputName: String, inputAge: String): Either[String, Person] =
 for {
   name <- parseName(inputName).right
   age <- parseAge(inputAge).right
 } yield Person(name, age)

Note that Either requires you to add .right at the end of each generator in the for expression. Although the convention is to place the valid result on the right, you must explicitly (and repetitively) indicate that you've done so by transforming the Either to a RightProjection by invoking .right at each step. Given this implementation, the parsePerson method will now short-circuit at the first sign of trouble (as it did when we used an Option), but you now get the first error message returned in a Left. Here are some examples:

parsePerson("Bridget Jones", "29")
// Result: Right(Person(Bridget Jones,29))

parsePerson("Bridget Jones", "")
// Result: Left("" is not a valid integer)

parsePerson("Bridget Jones", "-29")
// Result: Left("-29" is not a valid age)

parsePerson("", "")
// Result: Left("" is not a valid name)

== An Either with “attitude” ==

Because Or declares one alternative to be “good” and the other “bad,” it is more convenient than Either in this kind of situation. One difference to note with Or is that the Good alternative is on the left, Bad on the right. The reason is that Or is designed to be written using infix notation, and placing the “happy path” first is more readable. For example, instead of writing:

Or[Int, ErrorMessage]

You can write:

Int Or ErrorMessage

Here's how the parseName method might be written using an Or, where ErrorMessage is a type alias for String declared in the org.scalactic package object:

import org.scalactic._

def parseName(input: String): String Or ErrorMessage = {
 val trimmed = input.trim
 if (!trimmed.isEmpty) Good(trimmed) else Bad(s""""${input}" is not a valid name""")
}

You can think of the String Or ErrorMessage result type like this:

The parseName method will return a name String or, if the input string is not a valid name, an ErrorMessage.

Here's how the parseAge method might be written:

def parseAge(input: String): Int Or ErrorMessage = {
 try {
   val age = input.trim.toInt
   if (age >= 0) Good(age) else Bad(s""""${age}" is not a valid age""")
 }
 catch {
   case _: NumberFormatException => Bad(s""""${input}" is not a valid integer""")
 }
}

Given these implementations, here's how you'd write the parsePerson method:

def parsePerson(inputName: String, inputAge: String): Person Or ErrorMessage =
 for {
   name <- parseName(inputName)
   age <- parseAge(inputAge)
 } yield Person(name, age)

Because of Or's attitude, you need not write .good at the end of each generator. Or will keep going so long as each step produces a Good, short circuiting at the first sign of a Bad. Here are a few invocations of this parsePerson method:

parsePerson("Bridget Jones", "29")
// Result: Good(Person(Bridget Jones,29))

parsePerson("Bridget Jones", "")
// Result: Bad("" is not a valid integer)

parsePerson("Bridget Jones", "-29")
// Result: Bad("-29" is not a valid age)

parsePerson("", "")
// Result: Bad("" is not a valid name)

== Accumulating errors with Or ==

Another difference between Or and Either is that Or enables you to accumulate errors if the Bad type is an Every. An Every is similar to a Seq in that it contains ordered elements, but different from Seq in that it cannot be empty. An Every is either a One, which contains one and only one element, or a Many, which contains two or more elements.

Note: an Or whose Bad type is an Every, or one of its subtypes, is called an “accumulating Or.”

To rewrite the previous example so that errors can be accumulated, you need first to return an Every as the Bad type. Here's how you'd change the parseName method:

def parseName(input: String): String Or One[ErrorMessage] = {
 val trimmed = input.trim
 if (!trimmed.isEmpty) Good(trimmed) else Bad(One(s""""${input}" is not a valid name"""))
}

Because parseName will either return a valid name String wrapped in a Good, or one error message, wrapped in a Bad, you would write the Bad type as One[ErrorMessage]. The same is true for parseAge:

def parseAge(input: String): Int Or One[ErrorMessage] = {
 try {
   val age = input.trim.toInt
   if (age >= 0) Good(age) else Bad(One(s""""${age}" is not a valid age"""))
 }
 catch {
   case _: NumberFormatException => Bad(One(s""""${input}" is not a valid integer"""))
 }
}

Because a for expression short-circuits on the first Bad encountered, you'll need to use a different approach to write the parsePerson method. In this example, the withGood method from trait Accumulation will do the trick:

import Accumulation._

def parsePerson(inputName: String, inputAge: String): Person Or Every[ErrorMessage] = {
 val name = parseName(inputName)
 val age = parseAge(inputAge)
 withGood(name, age) { Person(_, _) }
}

Trait Accumulation offers overloaded withGood methods that take 1 to 22 accumulating Ors, plus a function taking the same number of corresponding Good values. In this example, if both name and age are Goods, the withGood method will pass the good name String and age Int to the Person(_, _) function, and return the resulting Person object wrapped in a Good. If either name and age, or both, are Bad, withGood will return the accumulated errors in a Bad.

The result of parsePerson, if Bad, will therefore contain either one or two error messages, i.e., the result will either be a One or a Many. As a result, the result type of parsePerson must be Person Or Every[ErrorMessage]. Regardless of whether a Bad result contains one or two error messages, it will contain every error message. Here's some invocations of this accumulating version of parsePerson:

parsePerson("Bridget Jones", "29")
// Result: Good(Person(Bridget Jones,29))

parsePerson("Bridget Jones", "")
// Result: Bad(One("" is not a valid integer))

parsePerson("Bridget Jones", "-29")
// Result: Bad(One("-29" is not a valid age))

parsePerson("", "")
// Result: Bad(Many("" is not a valid name, "" is not a valid integer))

Note that in the last example, the Bad contains an error message for both name and age.

== Other ways to accumulate errors ==

The Accumlation trait also enables other ways of accumulating errors.

=== Using combined ===

If you have a collection of accumulating Ors, for example, you can combine them into one Or using combined, like this:

List(parseAge("29"), parseAge("30"), parseAge("31")).combined
// Result: Good(List(29, 30, 31))

List(parseAge("29"), parseAge("-30"), parseAge("31")).combined
// Result: Bad(One("-30" is not a valid age))

List(parseAge("29"), parseAge("-30"), parseAge("-31")).combined
// Result: Bad(Many("-30" is not a valid age, "-31" is not a valid age))

=== Using validatedBy ===

Or if you have a collection of values and a function that transforms that type of value into an accumulating Ors, you can validate the values using the function using validatedBy, like this:

List("29", "30", "31").validatedBy(parseAge)
// Result: Good(List(29, 30, 31))

List("29", "-30", "31").validatedBy(parseAge)
// Result: Bad(One("-30" is not a valid age))

List("29", "-30", "-31").validatedBy(parseAge)
// Result: Bad(Many("-30" is not a valid age, "-31" is not a valid age))

=== Using zip ===

You can also zip two accumulating Ors together. If both are Good, you'll get a Good tuple containin both original Good values. Otherwise, you'll get a Bad containing every error message. Here are some examples:

parseName("Dude") zip parseAge("21")
// Result: Good((Dude,21))

parseName("Dude") zip parseAge("-21")
// Result: Bad(One("-21" is not a valid age))

parseName("") zip parseAge("-21")
// Result: Bad(Many("" is not a valid name, "-21" is not a valid age))

=== Using when ===

In addition, given an accumlating Or, you can pass one or more validation functions to when on the Or to submit that Or to further scrutiny. A validation function accepts a Good type and returns a Validation[E], where E is the type in the Every in the Bad type. For an Int Or One[ErrorMessage], for example the validation function type would be Int => Validation[ErrorMessage]. Here are a few examples:

def isRound(i: Int): Validation[ErrorMessage] =
 if (i % 10 == 0) Pass else Fail(i + " was not a round number")

def isDivBy3(i: Int): Validation[ErrorMessage] =
 if (i % 3 == 0) Pass else Fail(i + " was not divisible by 3")

If the Or on which you call when is already Bad, you get the same (Bad) Or back, because no Good value exists to pass to the valiation functions:

parseAge("-30").when(isRound, isDivBy3)
// Result: Bad(One("-30" is not a valid age))

If the Or on which you call when is Good, and also passes all the validation functions (i.e., the all return None), you again get the same Or back, but this time, a Good one:

parseAge("30").when(isRound, isDivBy3)
// Result: Good(30)

If one or more of the validation functions fails, however, you'll get a Bad back contining every error. Here are some examples:

parseAge("33").when(isRound, isDivBy3)
// Result: Bad(One(33 was not a round number))

parseAge("20").when(isRound, isDivBy3)
// Result: Bad(One(20 was not divisible by 3))

parseAge("31").when(isRound, isDivBy3)
// Result: Bad(Many(31 was not a round number, 31 was not divisible by 3))

Note that you can use when to accumulate errors in a for expression involving an accumulating Or, like this:

for (age <- parseAge("-30") when (isRound, isDivBy3)) yield age
// Result: Bad(One("-30" is not a valid age))

for (age <- parseAge("30") when (isRound, isDivBy3)) yield age
// Result: Good(30)

for (age <- parseAge("33") when (isRound, isDivBy3)) yield age
// Result: Bad(One(33 was not a round number))

for (age <- parseAge("20") when (isRound, isDivBy3)) yield age
// Result: Bad(One(20 was not divisible by 3))

for (age <- parseAge("31") when (isRound, isDivBy3)) yield age
// Result: Bad(Many(31 was not a round number, 31 was not divisible by 3))

== Much ado about Nothing ==

Because Or has two types, but each of its two subtypes only takes a value of one or the other type, the Scala compiler will infer Nothing for the unspecified type:

scala> Good(3)
res0: org.scalactic.Good[Int,Nothing] = Good(3)

scala> Bad("oops")
res1: org.scalactic.Bad[Nothing,String] = Bad(oops)

Often Nothing will work fine, as it will be widened as soon as the compiler encounters a more specific type. Sometimes, however, you may need to specify it. In such situations you can use this syntax:

scala> Good(3).orBad[String]
res2: org.scalactic.Good[Int,String] = Good(3)

scala> Good[Int].orBad("oops")
res3: org.scalactic.Bad[Int,String] = Bad(oops)

If you want to specify both types, because you don't like the inferred type, you can do so like this:

scala> Good[AnyVal, String](3)
res4: org.scalactic.Good[AnyVal,String] = Good(3)

scala> Bad[Int, ErrorMessage]("oops")
res5: org.scalactic.Bad[Int,org.scalactic.ErrorMessage] = Bad(oops)

But you may find the code is clearer if you instead use a type ascription, like this:

scala> Good(3): AnyVal Or String
res6: org.scalactic.Or[AnyVal,String] = Good(3)

scala> Bad("oops"): Int Or ErrorMessage
res7: org.scalactic.Or[Int,org.scalactic.ErrorMessage] = Bad(oops)

Note: The Or hierarchy was inspired in part by the disjoint union (/) and Validation types of scalaz, the ProcessResult type of Typesafe Activator, and the Result type of ScalaKittens.

Companion:
object
Source:
Or.scala
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
class Bad[B]
class Good[G]

Value members

Abstract methods

def accumulating: Or[G, One[B]]

Converts this Or to an Or with the same Good type and a Bad type consisting of One parameterized by this Or's Bad type.

Converts this Or to an Or with the same Good type and a Bad type consisting of One parameterized by this Or's Bad type.

For example, invoking the accumulating method on an Int Or ErrorMessage would convert it to an Int Or One[ErrorMessage]. This result type, because the Bad type is an Every, can be used with the mechanisms provided in trait Accumulation to accumulate errors.

Note that if this Or is already an accumulating Or, the behavior of this accumulating method does not change. For example, if you invoke accumulating on an Int Or One[ErrorMessage] you will be rewarded with an Int Or One[One[ErrorMessage]].

Returns:

this Good, if this Or is a Good; or this Bad value wrapped in a One if this Or is a Bad.

Source:
Or.scala
def badMap[C](f: B => C): Or[G, C]

Maps the given function to this Or's value if it is a Bad or returns this if it is a Good.

Maps the given function to this Or's value if it is a Bad or returns this if it is a Good.

Value parameters:
f

the function to apply

Returns:

if this is a Bad, the result of applying the given function to the contained value wrapped in a Bad, else this Good is returned

Source:
Or.scala
def exists(p: G => Boolean): Boolean

Returns true if this Or is a Good and the predicate p returns true when applied to this Good's value.

Returns true if this Or is a Good and the predicate p returns true when applied to this Good's value.

Note: The exists method will return the same result as forall if this Or is a Good, but the opposite result if this Or is a Bad.

Value parameters:
p

the predicate to apply to the Good value, if this is a Good

Returns:

the result of applying the passed predicate p to the Good value, if this is a Good, else false

Source:
Or.scala
def filter[C >: B](f: G => Validation[C]): Or[G, C]

Returns this Or if either 1) it is a Bad or 2) it is a Good and applying the validation function f to this Good's value returns Pass; otherwise, returns a new Bad containing the error value contained in the Fail resulting from applying the validation function f to this Good's value.

Returns this Or if either 1) it is a Bad or 2) it is a Good and applying the validation function f to this Good's value returns Pass; otherwise, returns a new Bad containing the error value contained in the Fail resulting from applying the validation function f to this Good's value.

For examples of filter used in for expressions, see the main documentation for trait Validation.

Value parameters:
f

the validation function to apply

Returns:

a Good if this Or is a Good that passes the validation function, else a Bad.

Source:
Or.scala
def flatMap[H, C >: B](f: G => Or[H, C]): Or[H, C]

Returns the given function applied to the value contained in this Or if it is a Good, or returns this if it is a Bad.

Returns the given function applied to the value contained in this Or if it is a Good, or returns this if it is a Bad.

Value parameters:
f

the function to apply

Returns:

if this is a Good, the result of applying the given function to the contained value wrapped in a Good, else this Bad is returned

Source:
Or.scala
def fold[V](gf: G => V, bf: B => V): V

Folds this Or into a value of type V by applying the given gf function if this is a Good else the given bf function if this is a Bad.

Folds this Or into a value of type V by applying the given gf function if this is a Good else the given bf function if this is a Bad.

Value parameters:
bf

the function to apply to this Or's Bad value, if it is a Bad

gf

the function to apply to this Or's Good value, if it is a Good

Returns:

the result of applying the appropriate one of the two passed functions, gf or bf, to this Or's value

Source:
Or.scala
def forall(f: G => Boolean): Boolean

Returns true if either this Or is a Bad or if the predicate p returns true when applied to this Good's value.

Returns true if either this Or is a Bad or if the predicate p returns true when applied to this Good's value.

Note: The forall method will return the same result as exists if this Or is a Good, but the opposite result if this Or is a Bad.

Value parameters:
p

the predicate to apply to the Good value, if this is a Good

Returns:

the result of applying the passed predicate p to the Good value, if this is a Good, else true

Source:
Or.scala
def foreach(f: G => Unit): Unit

Applies the given function f to the contained value if this Or is a Good; does nothing if this Or is a Bad.

Applies the given function f to the contained value if this Or is a Good; does nothing if this Or is a Bad.

Value parameters:
f

the function to apply

Source:
Or.scala
def get: G

Returns the Or's value if it is a Good or throws NoSuchElementException if it is a Bad.

Returns the Or's value if it is a Good or throws NoSuchElementException if it is a Bad.

Returns:

the contained value if this is a Good

Throws:
NoSuchElementException

if this is a Bad

Source:
Or.scala
def getOrElse[H >: G](default: => H): H

Returns, if this Or is Good, this Good's value; otherwise returns the result of evaluating default.

Returns, if this Or is Good, this Good's value; otherwise returns the result of evaluating default.

Value parameters:
default

the default expression to evaluate if this Or is a Bad

Returns:

the contained value, if this Or is a Good, else the result of evaluating the given default

Source:
Or.scala
def map[H](f: G => H): Or[H, B]

Maps the given function to this Or's value if it is a Good or returns this if it is a Bad.

Maps the given function to this Or's value if it is a Good or returns this if it is a Bad.

Value parameters:
f

the function to apply

Returns:

if this is a Good, the result of applying the given function to the contained value wrapped in a Good, else this Bad is returned

Source:
Or.scala
def orElse[H >: G, C >: B](alternative: => Or[H, C]): Or[H, C]

Returns this Or if it is a Good, otherwise returns the result of evaluating the passed alternative.

Returns this Or if it is a Good, otherwise returns the result of evaluating the passed alternative.

Value parameters:
alternative

the alternative by-name to evaluate if this Or is a Bad

Returns:

this Or, if it is a Good, else the result of evaluating alternative

Source:
Or.scala
def recover[H >: G](f: B => H): Or[H, B]

Maps the given function to this Or's value if it is a Bad, transforming it into a Good, or returns this if it is already a Good.

Maps the given function to this Or's value if it is a Bad, transforming it into a Good, or returns this if it is already a Good.

Value parameters:
f

the function to apply

Returns:

if this is a Bad, the result of applying the given function to the contained value wrapped in a Good, else this Good is returned

Source:
Or.scala
def recoverWith[H >: G, C](f: B => Or[H, C]): Or[H, C]

Maps the given function to this Or's value if it is a Bad, returning the result, or returns this if it is already a Good.

Maps the given function to this Or's value if it is a Bad, returning the result, or returns this if it is already a Good.

Value parameters:
f

the function to apply

Returns:

if this is a Bad, the result of applying the given function to the contained value, else this Good is returned

Source:
Or.scala
def swap: Or[B, G]

Returns an Or with the Good and Bad types swapped: Bad becomes Good and Good becomes Bad.

Returns an Or with the Good and Bad types swapped: Bad becomes Good and Good becomes Bad.

Here's an example:

scala> val lyrics = Bad("Hey Jude, don't make it bad. Take a sad song and make it better.")
lyrics: org.scalactic.Bad[Nothing,String] =
   Bad(Hey Jude, don't make it bad. Take a sad song and make it better.)

scala> lyrics.swap
res12: org.scalactic.Or[String,Nothing] =
   Good(Hey Jude, don't make it bad. Take a sad song and make it better.)

Now that song will be rolling around in your head all afternoon. But at least it is a good song (thanks to swap).

Returns:

if this Or is a Good, its Good value wrapped in a Bad; if this Or is a Bad, its Bad value wrapped in a Good.

Source:
Or.scala
def toEither: Either[B, G]

Returns an Either: a Right containing the Good value, if this is a Good; a Left containing the Bad value, if this is a Bad.

Returns an Either: a Right containing the Good value, if this is a Good; a Left containing the Bad value, if this is a Bad.

Note that values effectively “switch sides” when convering an Or to an Either. If the type of the Or on which you invoke toEither is Or[Int, ErrorMessage] for example, the result will be an Either[ErrorMessage, Int]. The reason is that the convention for Either is that Left is used for “bad” values and Right is used for “good” ones.

Returns:

this Good value, wrapped in a Right, or this Bad value, wrapped in a Left.

Source:
Or.scala
def toOption: Option[G]

Returns a Some containing the Good value, if this Or is a Good, else None.

Returns a Some containing the Good value, if this Or is a Good, else None.

Returns:

the contained “good” value wrapped in a Some, if this Or is a Good; None if this Or is a Bad.

Source:
Or.scala
def toSeq: IndexedSeq[G]

Returns an immutable IndexedSeq containing the Good value, if this Or is a Good, else an empty immutable IndexedSeq.

Returns an immutable IndexedSeq containing the Good value, if this Or is a Good, else an empty immutable IndexedSeq.

Returns:

the contained “good” value in a lone-element Seq if this Or is a Good; an empty Seq if this Or is a Bad.

Source:
Or.scala
def toTry(implicit ev: B <:< Throwable): Try[G]

Returns a Try: a Success containing the Good value, if this is a Good; a Failure containing the Bad value, if this is a Bad.

Returns a Try: a Success containing the Good value, if this is a Good; a Failure containing the Bad value, if this is a Bad.

Note: This method can only be called if the Bad type of this Or is a subclass of Throwable (or Throwable itself).

Note that values effectively “switch sides” when converting an Or to an Either. If the type of the Or on which you invoke toEither is Or[Int, ErrorMessage] for example, the result will be an Either[ErrorMessage, Int]. The reason is that the convention for Either is that Left is used for “bad” values and Right is used for “good” ones.

Returns:

this Good value, wrapped in a Right, or this Bad value, wrapped in a Left.

Source:
Or.scala
def transform[H, C](gf: G => Or[H, C], bf: B => Or[H, C]): Or[H, C]

Transforms this Or by applying the function gf to this Or's Good value if it is a Good, or by applying bf to this Or's Bad value if it is a Bad.

Transforms this Or by applying the function gf to this Or's Good value if it is a Good, or by applying bf to this Or's Bad value if it is a Bad.

Value parameters:
bf

the function to apply to this Or's Bad value, if it is a Bad

gf

the function to apply to this Or's Good value, if it is a Good

Returns:

the result of applying the appropriate one of the two passed functions, gf or bf, to this Or's value

Source:
Or.scala

Concrete methods

def withFilter[C >: B](f: G => Validation[C]): Or[G, C]

Currently just forwards to filter, and therefore, returns the same result.

Currently just forwards to filter, and therefore, returns the same result.

Source:
Or.scala

Deprecated methods

@deprecated("The asOr is no longer needed because Good(value).orBad[Type] and Good[Type].orBad(value) now return Or. You can delete invocations of asOr in those cases, otherwise, please use a type annotation to widen the type, like (Good(3): Int Or ErrorMessage).")
def asOr: Or[G, B]

The asOr method has been deprecated and will be removed in a future version of Scalactic. Please remove invocations of asOr in expressions of type Good(value).orBad[Type] and Good[Type].orBad(value) (which now return a type already widened to Or), otherwise please use a type annotation to widen the type, such as: (Good(3): Int Or ErrorMessage).

The asOr method has been deprecated and will be removed in a future version of Scalactic. Please remove invocations of asOr in expressions of type Good(value).orBad[Type] and Good[Type].orBad(value) (which now return a type already widened to Or), otherwise please use a type annotation to widen the type, such as: (Good(3): Int Or ErrorMessage).

Deprecated
Source:
Or.scala

Inherited methods

def canEqual(that: Any): Boolean
Inherited from:
Equals
def productArity: Int
Inherited from:
Product
def productElement(n: Int): Any
Inherited from:
Product
def productElementName(n: Int): String
Inherited from:
Product
def productElementNames: Iterator[String]
Inherited from:
Product
def productIterator: Iterator[Any]
Inherited from:
Product
def productPrefix: String
Inherited from:
Product

Concrete fields

val isBad: Boolean

Indicates whether this Or is a Bad

Indicates whether this Or is a Bad

Returns:

true if this Or is a Bad, false if it is a Good.

Source:
Or.scala
val isGood: Boolean

Indicates whether this Or is a Good

Indicates whether this Or is a Good

Returns:

true if this Or is a Good, false if it is a Bad.

Source:
Or.scala