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]].
this Good, if this Or is a Good; or this Bad value wrapped in a One if
this Or is a Bad.
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.
the function to apply
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
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.
the predicate to apply to the Good value, if this is a Good
the result of applying the passed predicate p to the Good value, if this is a Good, else false
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.
the validation function to apply
a Good if this Or is a Good that passes the validation function, else 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.
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.
the function to apply
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
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.
the function to apply to this Or's Good value, if it is a Good
the function to apply to this Or's Bad value, if it is a Bad
the result of applying the appropriate one of the two passed functions, gf or bf, to this Or'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.
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.
the result of applying the passed predicate p to the Good value, if this is a Good, else true
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.
the function to apply
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.
the contained value if this is a Good
if this is a Bad
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.
the default expression to evaluate if this Or is a Bad
the contained value, if this Or is a Good, else the result of evaluating the given default
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.
the function to apply
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
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.
the alternative by-name to evaluate if this Or is a Bad
this Or, if it is a Good, else the result of evaluating alternative
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.
the function to apply
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
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.
the function to apply
if this is a Bad, the result of applying the given function to the contained value,
else this Good is returned
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).
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.
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.
this Good value, wrapped in a Right, or this Bad value, wrapped in a Left.
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.
the contained “good” value wrapped in a Some, if this Or is a Good; None
if this Or is a Bad.
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.
the contained “good” value in a lone-element Seq if this Or is a Good; an empty Seq if
this Or 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.
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.
this Good value, wrapped in a Right, or this Bad value, wrapped in a Left.
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.
the function to apply to this Or's Good value, if it is a Good
the function to apply to this Or's Bad value, if it is a Bad
the result of applying the appropriate one of the two passed functions, gf or bf, to this Or's value
Indicates whether this Or is a Bad
Indicates whether this Or is a Bad
true if this Or is a Bad, false if it is a Good.
Indicates whether this Or is a Good
Indicates whether this Or is a Good
true if this Or is a Good, false if it is a Bad.
Currently just forwards to filter, and therefore, returns the same result.
Currently just forwards to filter, and therefore, returns the same result.
Represents a value that is one of two possible types, with one type being “good” and the other “bad.”
An
Orwill either be a “good” value wrapped in an instance ofGoodor a “bad” value wrapped in an instance ofBad.The motivation for
OrOrdiffers from Scala'sEithertype in thatEithertreats both itsLeftandRightalternatives in an identical manner, whereasOrtreats its two alternatives differently: it favorsGoodoverBad. Because of this, it is more convenient to work withOrs 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
Personclass from user input strings:You might write a method that parses the name from user input string and returns an
Option[String]:Noneif the string is empty or blank, else the trimmed string wrapped in aSome:You might also write a method that parses the age from user input string and returns an
Option[Int]:Noneif either the string is not a valid integer or it is a negative integer, else the string converted to an integer wrapped in aSome:With these building blocks you could write a method that parses name and age input strings and returns either a
Person, wrapped in aSome, orNoneif either the name or age, or both, was invalid:Here are some examples of invoking
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 anparsePerson:Eitherinstead. In this case, the desired result is a valid name or age, which by convention should be placed on the right of theEither. The left will be aStringerror message. Here's the newparseNamefunction, which returns anEither[String, String]: And here's the newparseAgefunction, which returns anEither[String, Int]: The newparsePersonmethod will return anEither[String, Person]: Note thatEitherrequires you to add.rightat the end of each generator in theforexpression. 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 theEitherto aRightProjectionby invoking.rightat each step. Given this implementation, theparsePersonmethod will now short-circuit at the first sign of trouble (as it did when we used anOption), but you now get the first error message returned in aLeft. Here are some examples: == AnEitherwith “attitude” == BecauseOrdeclares one alternative to be “good” and the other “bad,” it is more convenient thanEitherin this kind of situation. One difference to note withOris that theGoodalternative is on the left,Badon the right. The reason is thatOris 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: Here's how theparseNamemethod might be written using anOr, whereErrorMessageis a type alias forStringdeclared in theorg.scalacticpackage object: You can think of theStringOrErrorMessageresult type like this: Here's how theparseAgemethod might be written: Given these implementations, here's how you'd write theparsePersonmethod: Because ofOr's attitude, you need not write.goodat the end of each generator.Orwill keep going so long as each step produces aGood, short circuiting at the first sign of aBad. Here are a few invocations of thisparsePersonmethod: == Accumulating errors withOr== Another difference betweenOrandEitheris thatOrenables you to accumulate errors if theBadtype is anEvery. AnEveryis similar to aSeqin that it contains ordered elements, but different fromSeqin that it cannot be empty. AnEveryis either aOne, which contains one and only one element, or aMany, which contains two or more elements. Note: anOrwhoseBadtype is anEvery, or one of its subtypes, is called an “accumulatingOr.” To rewrite the previous example so that errors can be accumulated, you need first to return anEveryas theBadtype. Here's how you'd change theparseNamemethod: BecauseparseNamewill either return a valid nameStringwrapped in aGood, or one error message, wrapped in aBad, you would write theBadtype asOne[ErrorMessage]. The same is true forparseAge: Because aforexpression short-circuits on the firstBadencountered, you'll need to use a different approach to write theparsePersonmethod. In this example, thewithGoodmethod from traitAccumulationwill do the trick: TraitAccumulationoffers overloadedwithGoodmethods that take 1 to 22 accumulatingOrs, plus a function taking the same number of correspondingGoodvalues. In this example, if bothnameandageareGoods, thewithGoodmethod will pass the good nameStringand ageIntto thePerson(_, _)function, and return the resultingPersonobject wrapped in aGood. If eithernameandage, or both, areBad,withGoodwill return the accumulated errors in aBad. The result ofparsePerson, ifBad, will therefore contain either one or two error messages, i.e., the result will either be aOneor aMany. As a result, the result type ofparsePersonmust bePersonOrEvery[ErrorMessage]. Regardless of whether aBadresult contains one or two error messages, it will contain every error message. Here's some invocations of this accumulating version ofparsePerson: Note that in the last example, theBadcontains an error message for both name and age. == Other ways to accumulate errors == TheAccumlationtrait also enables other ways of accumulating errors. === Usingcombined=== If you have a collection of accumulatingOrs, for example, you can combine them into oneOrusingcombined, like this: === UsingvalidatedBy=== Or if you have a collection of values and a function that transforms that type of value into an accumulatingOrs, you can validate the values using the function usingvalidatedBy, like this: === Usingzip=== You can also zip two accumulatingOrs together. If both areGood, you'll get aGoodtuple containin both originalGoodvalues. Otherwise, you'll get aBadcontaining every error message. Here are some examples: === Usingwhen=== In addition, given an accumlatingOr, you can pass one or more validation functions towhenon theOrto submit thatOrto further scrutiny. A validation function accepts aGoodtype and returns aValidation[E], whereEis the type in theEveryin theBadtype. For anIntOrOne[ErrorMessage], for example the validation function type would beInt=>Validation[ErrorMessage]. Here are a few examples: If theOron which you callwhenis alreadyBad, you get the same (Bad)Orback, because noGoodvalue exists to pass to the valiation functions: If theOron which you callwhenisGood, and also passes all the validation functions (i.e., the all returnNone), you again get the sameOrback, but this time, aGoodone: If one or more of the validation functions fails, however, you'll get aBadback contining every error. Here are some examples: Note that you can usewhento accumulate errors in aforexpression involving an accumulatingOr, like this: == Much ado aboutNothing== BecauseOrhas two types, but each of its two subtypes only takes a value of one or the other type, the Scala compiler will inferNothingfor 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)OftenNothingwill 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: TheOrhierarchy was inspired in part by the disjoint union (\/) andValidationtypes ofscalaz, theProcessResulttype of Typesafe Activator, and theResulttype of ScalaKittens.