org.scalactic.TripleEqualsSupport.scala Maven / Gradle / Ivy
/* * Copyright 2001-2013 Artima, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.scalactic import TripleEqualsSupport._ /** * Trait that defines abstract methods used to enforce compile-time type constraints for equality comparisons, and definesB * @return an===and!==operators * used by matchers. * ** The abstract methods of this trait are selectively implemented as implicit by subclasses to enable a spectrum of type constraints for the *
* *===and!==operators. As an illustration, if in the expression,a === b, the type ofa* isAandbisB, the following three levels of compile-time checking can be obtained from *TripleEqualsSupportsubtraits: ** Unchecked -
* *AandBcan be any two types. This (weakest) constraint level is available from * subtraitsTripleEquals. ** Conversion checked -
* *Amust be a subtype ofB, or vice versa, or an implicit conversion must be available that converts *AtoB, or vice versa. (BothAandBcan be the same type, because a type is considered a subtype * of itself.) * This (intermediate) constraint level is available from subtraitsConversionCheckedTripleEquals. ** Type checked -
* *Amust be a subtype ofB, or vice versa. * (BothAandBcan be the same type, because a type is considered a subtype * of itself.) * This (strongest) constraint level is available from subtraitsTypeCheckedTripleEquals. ** This trait defines all methods that need to be defined implicitly by the six subtraits so that if multiple subtraits are used together, the inner-most * subtrait in scope can not only enable the implicits it needs by overriding or hiding those methods (currently-in-scope as regular, non-implicit methods) and making * them implicit, it can also disable any implicits enabled by its sibling subtraits in enclosing scopes. For example, if your test class mixes * in
* *TypeCheckedTripleEquals, inside your test class the following methods will be implicit: **
* *- *
convertToCheckingEqualizer- *
typeCheckedConstraint- *
lowPriorityTypeCheckedConstraint- *
convertEquivalenceToAToBConstraint- *
convertEquivalenceToBToAConstraint* If in the body of a test you want to turn off the type checking, you can import the members * of
* *TripleEqualsin the body of that test. This will not only hide * non-implicit methodsconvertToEqualizerunconstrainedEqualityofTypeCheckedTripleEquals, * replacing those with implicit ones defined inTripleEquals, it will also hide the three methods made implicit inTypeCheckedTripleEquals* (and listed above), replacing them by non-implicit ones. ** In short, you should be able to select a primary constraint level via either a mixin or import, then change that in nested scopes * however you want, again either through a mixin or import, without getting any implicit conversion ambiguity. The innermost constraint level in scope * will always be in force. *
* * @author Bill Venners */ trait TripleEqualsSupport { /** * Class used via an implicit conversion to enable any two objects to be compared with *
===and!==with aBooleanresult and no enforced type constraint between * two object types. For example: * ** assert(a === b) * assert(c !== d) ** ** You can also check numeric values against another with a tolerance. Here are some examples: *
* ** assert(a === (2.0 +- 0.1)) * assert(c !== (2.0 +- 0.1)) ** * @param leftSide An object to convert toEqualizer, which represents the value * on the left side of a===or!==invocation. * * @author Bill Venners */ class Equalizer[L](val leftSide: L) { // Note: This is called leftSide not left to avoid a conflict with scalaz's implicit that adds left /** * Compare two objects for equality, returning aBoolean, using theEqualitytype class passed asequality. * * @param rightSide the object to compare for equality withleftSide, passed to the constructor * @param equality an implicitEqualitytype class that defines a way of calculating equality for objects of typeL* @return true if theleftSideandrightSideobjects are equal according to the passedEqualitytype class. */ def ===(rightSide: Any)(implicit equality: Equality[L]): Boolean = equality.areEqual(leftSide, rightSide) /** * Compare two objects for inequality, returning aBoolean, using theEqualitytype class passed asequality. * * @param rightSide the object to compare for inequality withleftSide, passed to the constructor * @param equality an implicitEqualitytype class that defines a way of calculating equality for objects of typeL* @return true if theleftSideandrightSideobjects are not equal according to the passedEqualitytype class. */ def !==(rightSide: Any)(implicit equality: Equality[L]): Boolean = !equality.areEqual(leftSide, rightSide) /** * Determine whether a numeric object is within the passedSpread, returning aBoolean. * * @param spread theSpreadagainst which to compare the value passed to the constructor asleftSide* @return true if the value passed to the constructor asleftSideis within theSpreadpassed to this method. */ def ===(spread: Spread[L]): Boolean = if (spread != null) spread.isWithin(leftSide) else leftSide == spread /** * Determine whether a numeric object is outside the passedSpread, returning aBoolean. * * @param spread theSpreadagainst which to compare the value passed to the constructor asleftSide* @return true if the value passed to the constructor asleftSideis not within theSpreadpassed to this method. */ def !==(spread: Spread[L]): Boolean = if (spread != null) !spread.isWithin(leftSide) else leftSide != spread /** * Determine whether an object reference isnull. * * @param literalNull anullvalue against which to compare the value passed to the constructor asleftSidefor equality * @return true if the value passed to the constructor asleftSideisnull. */ def ===(literalNull: Null): Boolean = leftSide == null /** * Determines whether an object reference is non-null. * * @param literalNull anullvalue against which to compare the value passed to the constructor asleftSidefor inequality * @return true if the value passed to the constructor asleftSideis non-null. */ def !==(literalNull: Null): Boolean = leftSide != null } /** * Class used via an implicit conversion to enable two objects to be compared with *===and!==with aBooleanresult and an enforced type constraint between * two object types. For example: * ** assert(a === b) * assert(c !== d) ** ** You can also check numeric values against another with a tolerance. Here are some examples: *
* ** assert(a === (2.0 +- 0.1)) * assert(c !== (2.0 +- 0.1)) ** * @param leftSide An object to convert toEqualizer, which represents the value * on the left side of a===or!==invocation. * * @author Bill Venners */ class CheckingEqualizer[L](val leftSide: L) { // Note: This is called leftSide not left to avoid a conflict with scalaz's implicit that adds left /** * Compare two objects for equality, returning aBoolean, using theConstraintinstance passed asconstraint. * * @param rightSide the object to compare for equality withleftSide, passed to the constructor * @param constraint an implicitConstraintinstance that enforces a relationship between typesLandRand * defines a way of calculating equality for objects of typeL* @return true if theleftSideandrightSideobjects are equal according to the passedConstraintinstance. */ def ===[R](rightSide: R)(implicit constraint: L CanEqual R): Boolean = constraint.areEqual(leftSide, rightSide) /** * Compare two objects for inequality, returning aBoolean, using theConstraintinstance passed asconstraint. * * @param rightSide the object to compare for inequality withleftSide, passed to the constructor * @param constraint an implicitConstraintinstance that enforces a relationship between typesLandRand * defines a way of calculating equality for objects of typeL* @return true if theleftSideandrightSideobjects are not equal according to the passedConstraintinstance. */ def !==[R](rightSide: R)(implicit constraint: L CanEqual R): Boolean = !constraint.areEqual(leftSide, rightSide) /** * Determine whether a numeric object is within the passedSpread, returning aBoolean. * * @param spread theSpreadagainst which to compare the value passed to the constructor asleftSide* @return true if the value passed to the constructor asleftSideis not within theSpreadpassed to this method. */ def ===(spread: Spread[L]): Boolean = if (spread != null) spread.isWithin(leftSide) else leftSide == spread /** * Determine whether a numeric object is outside the passedSpread, returning aBoolean. * * @param spread theSpreadagainst which to compare the value passed to the constructor asleftSide* @return true if the value passed to the constructor asleftSideis not within theSpreadpassed to this method. */ def !==(spread: Spread[L]): Boolean = if (spread != null) !spread.isWithin(leftSide) else leftSide != spread } /** * Returns anEquality[A]for any typeAthat determines equality * by first calling.deepon anyArray(on either the left or right side), * then comparing the resulting objects with==. * * @return a defaultEqualityfor typeA*/ def defaultEquality[A]: Equality[A] = Equality.default /** * Converts to anEqualizerthat provides===and!==operators that * result inBooleanand enforce no type constraint. * ** This method is overridden and made implicit by subtrait
* * @param left the object whose type to convert toTripleEqualsand overriden as non-implicit by the other * subtraits in this package. *Equalizer. * @throws NullPointerException ifleftisnull. */ def convertToEqualizer[T](left: T): Equalizer[T] /** * Converts to anCheckingEqualizerthat provides===and!==operators * that result inBooleanand enforce a type constraint. * ** This method is overridden and made implicit by subtraits
* * @param left the object whose type to convert toTypeCheckedTripleEqualsand *ConversionCheckedTripleEquals, and overriden as * non-implicit by the other subtraits in this package. *CheckingEqualizer. * @throws NullPointerException ifleftisnull. */ def convertToCheckingEqualizer[T](left: T): CheckingEqualizer[T] /** * Provides anA CanEqual Binstance for any two typesAandB, with no type constraint enforced, given an * implicitEquality[A]. * ** The returned
* *Constraint'sareEqualmethod uses the implicitly passedEquality[A]'s *areEqualmethod to determine equality. ** This method is overridden and made implicit by subtraits
* * @param equalityOfA anTripleEqualsand * overriden as non-implicit by the other subtraits in this package. *Equality[A]type class to which theConstraint.areEqualmethod will delegate to determine equality. * @return anA CanEqual Binstance whoseareEqualmethod delegates to theareEqualmethod of * the passedEquality[A]. */ def unconstrainedEquality[A, B](implicit equalityOfA: Equality[A]): A CanEqual B /** * Provides anA CanEqual Bfor any two typesAandB, enforcing the type constraint * thatAmust be a subtype ofB, given an implicitEquivalence[B]. * ** The returned
* *Constraint'sareEqualmethod uses the implicitly passedEquivalence[A]'s *areEquivalentmethod to determine equality. ** This method is overridden and made implicit by subtraits *
* * @param equivalenceOfB anLowPriorityTypeCheckedConstraint(extended by *TypeCheckedTripleEquals), and * overriden as non-implicit by the other subtraits in this package. *Equivalence[B]type class to which theConstraint.areEqualmethod * will delegate to determine equality. * @param ev evidence thatAis a subype ofA CanEqual Binstance whoseareEqualmethod delegates to the *areEquivalentmethod of the passedEquivalence[B]. */ def lowPriorityTypeCheckedConstraint[A, B](implicit equivalenceOfB: Equivalence[B], ev: A <:< B): A CanEqual B /** * Provides aA CanEqual Bfor any two typesAandB, enforcing the type constraint * thatAmust be a subtype ofB, given an explicitEquivalence[B]. * ** This method is used to enable the
* *ExplicitlyDSL for *TypeCheckedTripleEqualsby requiring an explicitEquivalance[B], but * taking an implicit function that provides evidence thatAis a subtype of B. ** The returned
* *Constraint'sareEqualmethod uses the implicitly passedEquivalence[B]'s *areEquivalentmethod to determine equality. ** This method is overridden and made implicit by subtraits *
* * @param equivalenceOfB anLowPriorityTypeCheckedConstraint(extended by *TypeCheckedTripleEquals), and * overriden as non-implicit by the other subtraits in this package. *Equivalence[B]type class to which theConstraint.areEqualmethod * will delegate to determine equality. * @param ev evidence thatAis a subype of B * @return anA CanEqual Binstance whoseareEqualmethod delegates to the *areEquivalentmethod of the passedEquivalence[B]. */ def convertEquivalenceToAToBConstraint[A, B](equivalenceOfB: Equivalence[B])(implicit ev: A <:< B): A CanEqual B /** * Provides anA CanEqual Binstance for any two typesAandB, enforcing the type constraint * thatBmust be a subtype ofA, given an implicitEquivalence[A]. * ** The returned
* *Constraint'sareEqualmethod uses the implicitly passedEquivalence[A]'s *areEquivalentmethod to determine equality. ** This method is overridden and made implicit by subtraits *
* * @param equalityOfA anTypeCheckedTripleEquals) and * overriden as non-implicit by the other subtraits in this package. *Equivalence[A]type class to which theConstraint.areEqualmethod will delegate to determine equality. * @param ev evidence thatBis a subype of A * @return anA CanEqual Binstance whoseareEqualmethod delegates to theareEquivalentmethod of * the passedEquivalence[A]. */ def typeCheckedConstraint[A, B](implicit equivalenceOfA: Equivalence[A], ev: B <:< A): A CanEqual B /** * Provides anA CanEqual Binstance for any two typesAandB, enforcing the type constraint * thatBmust be a subtype ofA, given an explicitEquivalence[A]. * ** This method is used to enable the
* *ExplicitlyDSL for *TypeCheckedTripleEqualsby requiring an explicitEquivalance[B], but * taking an implicit function that provides evidence thatAis a subtype of B. For example, underTypeCheckedTripleEquals, * this method (as an implicit method), would be used to compile this statement: ** def closeEnoughTo1(num: Double): Boolean = * (num === 1.0)(decided by forgivingEquality) ** ** The returned
* *Constraint'sareEqualmethod uses the implicitly passedEquivalence[A]'s *areEquivalentmethod to determine equality. ** This method is overridden and made implicit by subtraits *
* * @param equalityOfA anTypeCheckedTripleEquals) and * overriden as non-implicit by the other subtraits in this package. *Equivalence[A]type class to which theConstraint.areEqualmethod will delegate to determine equality. * @param ev evidence thatBis a subype of A * @return anA CanEqual Binstance whoseareEqualmethod delegates to theareEquivalentmethod of * the passedEquivalence[A]. */ def convertEquivalenceToBToAConstraint[A, B](equivalenceOfA: Equivalence[A])(implicit ev: B <:< A): A CanEqual B /** * Provides anA CanEqual Binstance for any two typesAandB, enforcing the type constraint thatAis * implicitly convertible toB, given an implicitEquivalence[B]. * ** The returned
* *Constraint'sareEqualmethod uses the implicitly passedEquivalence[B]'s *areEquivalentmethod to determine equality. ** This method is overridden and made implicit by subtraits *
* * @param equalityOfB anLowPriorityConversionCheckedConstraint(extended by *ConversionCheckedTripleEquals), and * overriden as non-implicit by the other subtraits in this package. *Equivalence[B]type class to which theConstraint.areEqualmethod will delegate to determine equality. * @param cnv an implicit conversion fromAto B * @return anA CanEqual Binstance whoseareEqualmethod delegates to theareEquivalentmethod of * the passedEquivalence[B]. */ def lowPriorityConversionCheckedConstraint[A, B](implicit equivalenceOfB: Equivalence[B], cnv: A => B): A CanEqual B /** * Provides anA CanEqual Binstance for any two typesAandB, enforcing the type constraint thatAis * implicitly convertible toB, given an explicitEquivalence[B]. * ** This method is used to enable the
* *ExplicitlyDSL for *ConversionCheckedTripleEqualsby requiring an explicitEquivalance[B], but * taking an implicit function that converts fromAto B. ** The returned
* *Constraint'sareEqualmethod uses the implicitly passedEquivalence[B]'s *areEquivalentmethod to determine equality. ** This method is overridden and made implicit by subtraits *
* * @param equalityOfB anLowPriorityConversionCheckedConstraint(extended by *ConversionCheckedTripleEquals), and * overriden as non-implicit by the other subtraits in this package. *Equivalence[B]type class to which theConstraint.areEqualmethod will delegate to determine equality. * @param cnv an implicit conversion fromAto B * @return anA CanEqual Binstance whoseareEqualmethod delegates to theareEquivalentmethod of * the passedEquivalence[B]. */ def convertEquivalenceToAToBConversionConstraint[A, B](equivalenceOfB: Equivalence[B])(implicit ev: A => B): A CanEqual B /** * Provides anA CanEqual Binstance for any two typesAandB, enforcing the type constraint thatBis * implicitly convertible toA, given an implicitEquivalence[A]. * ** The returned
* *Constraint'sareEqualmethod uses the implicitly passedEquivalence[A]'s *areEquivalentmethod to determine equality. ** This method is overridden and made implicit by subtraits *
* * @param equivalenceOfA anConversionCheckedTripleEquals) and * overriden as non-implicit by the other subtraits in this package. *Equivalence[A]type class to which theConstraint.areEqualmethod will delegate to determine equality. * @param cnv an implicit conversion fromBto A * @return anA CanEqual Binstance whoseareEqualmethod delegates to theareEquivalentmethod of * the passedEquivalence[A]. */ def conversionCheckedConstraint[A, B](implicit equivalenceOfA: Equivalence[A], cnv: B => A): A CanEqual B /** * Provides anA CanEqual Binstance for any two typesAandB, enforcing the type constraint thatBis * implicitly convertible toA, given an explicitEquivalence[A]. * ** This method is used to enable the
* *ExplicitlyDSL for *ConversionCheckedTripleEqualsby requiring an explicitEquivalance[A], but * taking an implicit function that converts fromBto A. For example, underConversionCheckedTripleEquals, * this method (as an implicit method), would be used to compile this statement: ** def closeEnoughTo1(num: Double): Boolean = * (num === 1.0)(decided by forgivingEquality) ** ** The returned
* *Constraint'sareEqualmethod uses the implicitly passedEquivalence[A]'s *areEquivalentmethod to determine equality. ** This method is overridden and made implicit by subtraits *
* * @param equivalenceOfA anConversionCheckedTripleEquals) and * overriden as non-implicit by the other subtraits in this package. *Equivalence[A]type class to which theConstraint.areEqualmethod will delegate to determine equality. * @param cnv an implicit conversion fromBto A * @return anA CanEqual Binstance whoseareEqualmethod delegates to theareEquivalentmethod of * the passedEquivalence[A]. */ def convertEquivalenceToBToAConversionConstraint[A, B](equivalenceOfA: Equivalence[A])(implicit ev: B => A): A CanEqual B /** * Returns aTripleEqualsInvocation[T], given an object of typeT, to facilitate * the “<left> should === <right>” syntax * ofMatchers. * * @param right the right-hand side value for an equality assertion * @return aTripleEqualsInvocationwrapping the passed right value, withexpectingEqual* set totrue. */ def ===[T](right: T): TripleEqualsInvocation[T] = new TripleEqualsInvocation[T](right, true) /** * Returns aTripleEqualsInvocation[T], given an object of typeT, to facilitate * the “<left> should !== <right>” syntax * ofMatchers. * * @param right the right-hand side value for an equality assertion * @return aTripleEqualsInvocationwrapping the passed right value, withexpectingEqual* set tofalse. */ def !==[T](right: T): TripleEqualsInvocation[T] = new TripleEqualsInvocation[T](right, false) /** * Returns aTripleEqualsInvocation[Null], given anullreference, to facilitate * the “<left> should === null” syntax * ofMatchers. * * @param right a null reference * @return aTripleEqualsInvocationwrapping the passednullvalue, withexpectingEqual* set totrue. */ def ===(right: Null): TripleEqualsInvocation[Null] = new TripleEqualsInvocation[Null](right, true) /** * Returns aTripleEqualsInvocation[Null], given anullreference, to facilitate * the “<left> should !== null” syntax * ofMatchers. * * @param right a null reference * @return aTripleEqualsInvocationwrapping the passednullvalue, withexpectingEqual* set tofalse. */ def !==(right: Null): TripleEqualsInvocation[Null] = new TripleEqualsInvocation[Null](right, false) /** * Returns aTripleEqualsInvocationOnSpread[T], given anSpread[T], to facilitate * the “<left> should === (<pivot> +- <tolerance>)” * syntax ofMatchers. * * @param right theSpread[T]against which to compare the left-hand value * @return aTripleEqualsInvocationOnSpreadwrapping the passedSpread[T]value, with *expectingEqualset totrue. */ def ===[T](right: Spread[T]): TripleEqualsInvocationOnSpread[T] = new TripleEqualsInvocationOnSpread[T](right, true) /** * Returns aTripleEqualsInvocationOnSpread[T], given anSpread[T], to facilitate * the “<left> should !== (<pivot> +- <tolerance>)” * syntax ofMatchers. * * @param right theSpread[T]against which to compare the left-hand value * @return aTripleEqualsInvocationOnSpreadwrapping the passedSpread[T]value, with *expectingEqualset tofalse. */ def !==[T](right: Spread[T]): TripleEqualsInvocationOnSpread[T] = new TripleEqualsInvocationOnSpread[T](right, false) } object TripleEqualsSupport { /** * An implementation ofConstraintfor two typesAandBthat requires anEquality[A]to * which itsareEqualmethod can delegate an equality comparison. * * @param equalityOfA anEqualitytype class forA*/ final class EqualityConstraint[A, B](equalityOfA: Equality[A]) extends (A CanEqual B) { /** * Indicates whether the objects passed asaandbare equal by returning the * result of invokingareEqual(a, b)on the passedequalityOfAobject. * * @param a a left-hand-side object being compared with another (right-hand-side one) for equality (e.g.,a == b) * @param b a right-hand-side object being compared with another (left-hand-side one) for equality (e.g.,a == b) */ def areEqual(a: A, b: B): Boolean = equalityOfA.areEqual(a, b) } /** * An implementation ofConstraintfor two typesAandBthat requires anEquality[B]* and a conversion function fromAtoB. * * @param equivalenceOfB anEquivalencetype class forB*/ final class AToBEquivalenceConstraint[A, B](equivalenceOfB: Equivalence[B], cnv: A => B) extends (A CanEqual B) { /** * Indicates whether the objects passed asaandbare equal by return the * result of invokingareEqual(cnv(a), b)on the passedequalityOfBobject. * ** In other words, the
* * @param a a left-hand-side object being compared with another (right-hand-side one) for equality (e.g.,aobject of typeAis first converted to aBvia the passed conversion * function,cnv, then compared for equality with thebobject. *a == b) * @param b a right-hand-side object being compared with another (left-hand-side one) for equality (e.g.,a == b) */ override def areEqual(a: A, b: B): Boolean = equivalenceOfB.areEquivalent(cnv(a), b) } /** * An implementation ofConstraintfor two typesAandBthat requires anEquality[A]* and a conversion function fromBtoA. * * @param equivalenceOfA anEquivalencetype class forA*/ final class BToAEquivalenceConstraint[A, B](equivalenceOfA: Equivalence[A], cnv: B => A) extends (A CanEqual B) { /** * Indicates whether the objects passed asaandbare equal by returning the * result of invokingareEqual(a, cnv(b))on the passedequalityOfAobject. * ** In other words, the
* * @param a a left-hand-side object being compared with another (right-hand-side one) for equality (e.g.,bobject of typeBis first converted to anAvia the passed conversion * function,cnv, then compared for equality with theaobject. *a == b) * @param b a right-hand-side object being compared with another (left-hand-side one) for equality (e.g.,a == b) */ override def areEqual(a: A, b: B): Boolean = equivalenceOfA.areEquivalent(a, cnv(b)) } /** * Facilitates the “should === (x += y)” and “should !== (x += y)” syntax of ScalaTest's matchers DSL. * ** Instances of this class are created and returned by the
* * @param spread the===and!==methods of * traitTripleEqualsSupport. *Spread[T]against which to compare the left-hand value * @param expectingEqualtrueif the result of a===invocation;falseif the result of a!==invocation. */ final case class TripleEqualsInvocationOnSpread[T](spread: Spread[T], expectingEqual: Boolean) /** * Facilitates the “should ===” and “should !==” syntax of ScalaTest's matchers DSL. * ** Instances of this class are created and returned by the
* * @param right the right-hand side value for an equality assertion * @param expectingEqual===and!==methods of * traitTripleEqualsSupport. *trueif the result of a===invocation;falseif the result of a!==invocation. */ final case class TripleEqualsInvocation[T](right: T, expectingEqual: Boolean) { override def toString: String = (if (expectingEqual) "===" else "!==") + " " + Prettifier.default(right) } /** * Class representing an spread (i.e., range) between two numbers. * ** The spread is expressed in terms of a
* * @param pivot the pivot number at the center of the spread * @param tolerance the tolerance that determines the high and low point of the spread * * @author Bill Venners */ final case class Spread[T : Numeric](pivot: T, tolerance: T) { private val numeric = implicitly[Numeric[T]] require(numeric.signum(tolerance) >= 0, "tolerance must be zero or greater, but was " + tolerance) private val max = numeric.plus(pivot, tolerance) private val min = numeric.minus(pivot, tolerance) /** * Determines whether the passedNumericpivot and tolerance. * The spread extends frompivot - tolerancetopivot + tolerance, inclusive. *Numericvaluenis within the spread represented * by thisSpreadinstance. */ def isWithin(n: T): Boolean = { numeric.gteq(n, min) && numeric.lteq(n, max) } /** * Returnstrueif the passed number,n, is within the spread represented by thisSpreadinstance * ** The purpose of this method, which will likely be used only rarely, is to achieve symmetry around the
* *===operator. The *TripleEqualstrait (and its type-checking siblingsTypeCheckedTripleEqualsandConversionCheckedTripleEquals) enable you to write: ** a === (1.0 +- 0.1) ** ** This method ensures the following mirrored form means the same thing: *
* ** (1.0 +- 0.1) === a ** * @param n a number that may or may not lie within this spread */ def ===(n: T): Boolean = isWithin(n) /** * Returnsfalseif the passed number,n, is within the spread represented by thisSpreadinstance * ** The purpose of this method, which will likely be used only rarely, is to achieve symmetry around the
* *!==operator. The *TripleEqualstrait (and its type-checking siblingsTypeCheckedTripleEqualsandConversionCheckedTripleEquals) enable you to write: ** a !== (1.0 +- 0.1) ** ** This method ensures the following mirrored form means the same thing: *
* ** (1.0 +- 0.1) !== a ** * @param n a number that may or may not lie within this spread */ def !==(n: T): Boolean = !isWithin(n) /** * Overrides toString to return "[pivot] +- [tolerance]" */ override def toString: String = Prettifier.default(pivot) + " +- " + Prettifier.default(tolerance) } }