Package

org.scalactic

anyvals

Permalink

package anyvals

Visibility
  1. Public
  2. All

Type Members

  1. trait CompileTimeAssertions extends AnyRef

    Permalink

    Trait providing assertion methods that can be called at compile time from macros to validate literals in source code.

    Trait providing assertion methods that can be called at compile time from macros to validate literals in source code.

    The intent of CompileTimeAssertions is to make it easier to create AnyVals that restrict the values of types for which Scala supports literals: Int, Long, Float, Double, Char, and String. For example, if you are using odd integers in many places in your code, you might have validity checks scattered throughout your code. Here's an example of a method that both requires an odd Int is passed (as a precondition, and ensures an odd * Int is returned (as a postcondition):

    def nextOdd(i: Int): Int = {
      def isOdd(x: Int): Boolean = x.abs % 2 == 1
      require(isOdd(i))
      (i + 2) ensuring (isOdd(_))
    }
    

    In either the precondition or postcondition check fails, an exception will be thrown at runtime. If you have many methods like this you may want to create a type to represent an odd Int, so that the checking for validity errors is isolated in just one place. By using an AnyVal you can avoid boxing the Int, which may be more efficient. This might look like:

    final class OddInt private (val value: Int) extends AnyVal {
      override def toString: String = s"OddInt($value)"
    }
    
    object OddInt {
      def apply(value: Int): OddInt = {
        require(value.abs % 2 == 1)
        new OddInt(value)
      }
    }
    

    An AnyVal cannot have any constructor code, so to ensure that any Int passed to the OddInt constructor is actually odd, the constructor must be private. That way the only way to construct a new OddInt is via the apply factory method in the OddInt companion object, which can require that the value be odd. This design eliminates the need for placing require and ensuring clauses anywhere else that odd Ints are needed, because the type promises the constraint. The nextOdd method could, therefore, be rewritten as:

    def nextOdd(oi: OddInt): OddInt = OddInt(oi.value + 2)
    

    Using the compile-time assertions provided by this trait, you can construct a factory method implemented vai a macro wthat causes a compile failure if OddInt.apply is passed anything besides an odd Int literal. Class OddInt would look exactly the same as before:

    final class OddInt private (val value: Int) extends AnyVal {
      override def toString: String = s"OddInt($value)"
    }
    

    In the companion object, however, the apply method would be implemented in terms of a macro. Because the apply method will only work with literals, you'll need a second method that can work an any expression of type Int. Although you could write a factory method that throws a runtime exception if a non-odd Int is passed, we recommend a from method that returns an Option. The returned Option can be processed to deal with the potential for non-odd values.

    object OddInt {
    
      // The from factory method validates at run time
      def from(value: Int): Option[OddInt] =
        if (OddIntMacro.isValid(value)) Some(new OddInt(value)) else None
    
      // The apply factory method validates at compile time
      import scala.language.experimental.macros
      def apply(value: Int): OddInt = macro OddIntMacro.apply
    }
    

    The apply method refers to a macro implementation method in class PosIntMacro. The macro implementation of any such method can look very similar to this one. The only changes you'd need to make is the isValid method implementation and the text of the error messages.

    import org.scalactic.anyvals.CompileTimeAssertions
    import reflect.macros.Context
    
    object OddIntMacro extends CompileTimeAssertions {
    
      // Validation method used at both compile- and run-time
      def isValid(i: Int): Boolean = i.abs % 2 == 1
    
      // Apply macro that performs a compile-time assertion
      def apply(c: Context)(value: c.Expr[Int]): c.Expr[OddInt] = {
    
        // Prepare potential compiler error messages
        val notValidMsg = "OddInt.apply can only be invoked on odd Int literals, like OddInt(3)."
        val notLiteralMsg = "OddInt.apply can only be invoked on Int literals, like " +
              "OddInt(3). Please use OddInt.from instead."
    
        // Validate via a compile-time assertion
        ensureValidIntLiteral(c)(value, notValidMsg, notLiteralMsg)(isValid)
    
        // Validated, so rewrite the apply call to a from call
        c.universe.reify { OddInt.from(value.splice).get }
      }
    }
    

    The isValid method just takes the underlying type and returns true if it is valid, else false. This method is placed here so the same valiation code can be used both in the from method at runtime and the apply macro at compile time. The apply actually does just two things. It calls a ensureValidIntLiteral, performing a compile-time assertion that value passed to apply is an Int literal that is valid (in this case, odd). If the assertion fails, ensureValidIntLiteral will complete abruptly with an exception that will contain an appropriate error message (one of the two you passed in) and cause a compiler error with that message. If the assertion succeeds, ensureValidIntLiteral will just return normally. The next line of code will then execute. This line of code must construct an AST (abstract syntax tree) of code that will replace the OddInt.apply invocation. We invoke the other factory method that returns an Option, and since we've proven at compile time that that Option will be defined, we call get on it.

    You may wish to use quasi-quotes instead of reify. The reason we use reify is that this also works on 2.10 without any additional plugin (i.e., you don't need macro paradise), and Scalactic supports 2.10.

  2. final class PosDouble extends AnyVal

    Permalink

    An AnyVal for positive Doubles.

    An AnyVal for positive Doubles.

    Note: a PosDouble may not equal 0. If you want positive number or 0, use PosZDouble.

    Because PosDouble is an AnyVal it will usually be as efficient as an Double, being boxed only when a Double would have been boxed.

    The PosDouble.apply factory method is implemented in terms of a macro that checks literals for validity at compile time. Calling PosDouble.apply with a literal Double value will either produce a valid PosDouble instance at run time or an error at compile time. Here's an example:

    scala> import anyvals._
    import anyvals._
    
    scala> PosDouble(1.0)
    res1: org.scalactic.anyvals.PosDouble = PosDouble(1.0)
    
    scala> PosDouble(0.0)
    <console>:14: error: PosDouble.apply can only be invoked on a positive (i > 0.0) floating point literal, like PosDouble(42.0).
                  PosDouble(0.0)
                           ^
    

    PosDouble.apply cannot be used if the value being passed is a variable (i.e., not a literal), because the macro cannot determine the validity of variables at compile time (just literals). If you try to pass a variable to PosDouble.apply, you'll get a compiler error that suggests you use a different factor method, PosDouble.from, instead:

    scala> val x = 1.0
    x: Double = 1.0
    
    scala> PosDouble(x)
    <console>:15: error: PosDouble.apply can only be invoked on a floating point literal, like PosDouble(42.0). Please use PosDouble.from instead.
                  PosDouble(x)
                           ^
    

    The PosDouble.from factory method will inspect the value at runtime and return an Option[PosDouble]. If the value is valid, PosDouble.from will return a Some[PosDouble], else it will return a None. Here's an example:

    scala> PosDouble.from(x)
    res4: Option[org.scalactic.anyvals.PosDouble] = Some(PosDouble(1.0))
    
    scala> val y = 0.0
    y: Double = 0.0
    
    scala> PosDouble.from(y)
    res5: Option[org.scalactic.anyvals.PosDouble] = None
    

    The PosDouble.apply factory method is marked implicit, so that you can pass literal Doubles into methods that require PosDouble, and get the same compile-time checking you get when calling PosDouble.apply explicitly. Here's an example:

    scala> def invert(pos: PosDouble): Double = Double.MaxValue - pos
    invert: (pos: org.scalactic.anyvals.PosDouble)Double
    
    scala> invert(1.1)
    res6: Double = 1.7976931348623157E308
    
    scala> invert(Double.MaxValue)
    res8: Double = 0.0
    
    scala> invert(0.0)
    <console>:15: error: PosDouble.apply can only be invoked on a positive (i > 0.0) floating point literal, like PosDouble(42.0).
                  invert(0.0)
                         ^
    
    scala> invert(-1.0)
    <console>:15: error: PosDouble.apply can only be invoked on a positive (i > 0.0) floating point literal, like PosDouble(42.0).
                  invert(-1.0)
                          ^
    
    

    This example also demonstrates that the PosDouble companion object also defines implicit widening conversions when a similar conversion is provided in Scala. This makes it convenient to use a PosDouble where a Double is needed. An example is the subtraction in the body of the invert method defined above, Double.MaxValue - pos. Although Double.MaxValue is a Double, which has no - method that takes a PosDouble (the type of pos), you can still subtract pos, because the PosDouble will be implicitly widened to Double.

  3. final class PosFloat extends AnyVal

    Permalink

    An AnyVal for positive Floats.

    An AnyVal for positive Floats.

    Note: a PosFloat may not equal 0. If you want positive number or 0, use PosZFloat.

    Because PosFloat is an AnyVal it will usually be as efficient as an Float, being boxed only when an Float would have been boxed.

    The PosFloat.apply factory method is implemented in terms of a macro that checks literals for validity at compile time. Calling PosFloat.apply with a literal Float value will either produce a valid PosFloat instance at run time or an error at compile time. Here's an example:

    scala> import anyvals._
    import anyvals._
    
    scala> PosFloat(1.0F)
    res0: org.scalactic.anyvals.PosFloat = PosFloat(1.0)
    
    scala> PosFloat(0.0F)
    <console>:14: error: PosFloat.apply can only be invoked on a positive (i > 0.0F) floating point literal, like PosFloat(42.0F).
                  PosFloat(0.0F)
                          ^
    

    PosFloat.apply cannot be used if the value being passed is a variable (i.e., not a literal), because the macro cannot determine the validity of variables at compile time (just literals). If you try to pass a variable to PosFloat.apply, you'll get a compiler error that suggests you use a different factor method, PosFloat.from, instead:

    scala> val x = 1.0F
    x: Float = 1.0
    
    scala> PosFloat(x)
    <console>:15: error: PosFloat.apply can only be invoked on a floating point literal, like PosFloat(42.0F). Please use PosFloat.from instead.
                  PosFloat(x)
                          ^
    

    The PosFloat.from factory method will inspect the value at runtime and return an Option[PosFloat]. If the value is valid, PosFloat.from will return a Some[PosFloat], else it will return a None. Here's an example:

    scala> PosFloat.from(x)
    res3: Option[org.scalactic.anyvals.PosFloat] = Some(PosFloat(1.0))
    
    scala> val y = 0.0F
    y: Float = 0.0
    
    scala> PosFloat.from(y)
    res4: Option[org.scalactic.anyvals.PosFloat] = None
    

    The PosFloat.apply factory method is marked implicit, so that you can pass literal Floats into methods that require PosFloat, and get the same compile-time checking you get when calling PosFloat.apply explicitly. Here's an example:

    scala> def invert(pos: PosFloat): Float = Float.MaxValue - pos
    invert: (pos: org.scalactic.anyvals.PosFloat)Float
    
    scala> invert(1.1F)
    res5: Float = 3.4028235E38
    
    scala> invert(Float.MaxValue)
    res6: Float = 0.0
    
    scala> invert(0.0F)
    <console>:15: error: PosFloat.apply can only be invoked on a positive (i > 0.0F) floating point literal, like PosFloat(42.0F).
                  invert(0.0F)
                         ^
    
    scala> invert(-1.1F)
    <console>:15: error: PosFloat.apply can only be invoked on a positive (i > 0.0F) floating point literal, like PosFloat(42.0F).
                  invert(-1.1F)
                          ^
    
    

    This example also demonstrates that the PosFloat companion object also defines implicit widening conversions when no loss of precision will occur. This makes it convenient to use a PosFloat where a Float or wider type is needed. An example is the subtraction in the body of the invert method defined above, Float.MaxValue - pos. Although Float.MaxValue is a Float, which has no - method that takes a PosFloat (the type of pos), you can still subtract pos, because the PosFloat will be implicitly widened to Float.

  4. final class PosInt extends AnyVal

    Permalink

    An AnyVal for positive Ints.

    An AnyVal for positive Ints.

    Note: a PosInt may not equal 0. If you want positive number or 0, use PosZInt.

    Because PosInt is an AnyVal it will usually be as efficient as an Int, being boxed only when an Int would have been boxed.

    The PosInt.apply factory method is implemented in terms of a macro that checks literals for validity at compile time. Calling PosInt.apply with a literal Int value will either produce a valid PosInt instance at run time or an error at compile time. Here's an example:

    scala> import anyvals._
    import anyvals._
    
    scala> PosInt(1)
    res0: org.scalactic.anyvals.PosInt = PosInt(1)
    
    scala> PosInt(0)
    <console>:14: error: PosInt.apply can only be invoked on a positive (i > 0) integer literal, like PosInt(42).
                  PosInt(0)
                        ^
    

    PosInt.apply cannot be used if the value being passed is a variable (i.e., not a literal), because the macro cannot determine the validity of variables at compile time (just literals). If you try to pass a variable to PosInt.apply, you'll get a compiler error that suggests you use a different factor method, PosInt.from, instead:

    scala> val x = 1
    x: Int = 1
    
    scala> PosInt(x)
    <console>:15: error: PosInt.apply can only be invoked on an integer literal, like PosInt(42). Please use PosInt.from instead.
                  PosInt(x)
                        ^
    

    The PosInt.from factory method will inspect the value at runtime and return an Option[PosInt]. If the value is valid, PosInt.from will return a Some[PosInt], else it will return a None. Here's an example:

    scala> PosInt.from(x)
    res3: Option[org.scalactic.anyvals.PosInt] = Some(PosInt(1))
    
    scala> val y = 0
    y: Int = 0
    
    scala> PosInt.from(y)
    res4: Option[org.scalactic.anyvals.PosInt] = None
    

    The PosInt.apply factory method is marked implicit, so that you can pass literal Ints into methods that require PosInt, and get the same compile-time checking you get when calling PosInt.apply explicitly. Here's an example:

    scala> def invert(pos: PosInt): Int = Int.MaxValue - pos
    invert: (pos: org.scalactic.anyvals.PosInt)Int
    
    scala> invert(1)
    res0: Int = 2147483646
    
    scala> invert(Int.MaxValue)
    res1: Int = 0
    
    scala> invert(0)
    <console>:15: error: PosInt.apply can only be invoked on a positive (i > 0) integer literal, like PosInt(42).
                  invert(0)
                         ^
    
    scala> invert(-1)
    <console>:15: error: PosInt.apply can only be invoked on a positive (i > 0) integer literal, like PosInt(42).
                  invert(-1)
                          ^
    
    

    This example also demonstrates that the PosInt companion object also defines implicit widening conversions when either no loss of precision will occur or a similar conversion is provided in Scala. (For example, the implicit conversion from Int to Float in Scala can lose precision.) This makes it convenient to use a PosInt where an Int or wider type is needed. An example is the subtraction in the body of the invert method defined above, Int.MaxValue - pos. Although Int.MaxValue is an Int, which has no - method that takes a PosInt (the type of pos), you can still subtract pos, because the PosInt will be implicitly widened to Int.

  5. final class PosLong extends AnyVal

    Permalink

    An AnyVal for positive Longs.

    An AnyVal for positive Longs.

    Note: a PosLong may not equal 0. If you want positive number or 0, use PosZLong.

    Because PosLong is an AnyVal it will usually be as efficient as an Long, being boxed only when an Long would have been boxed.

    The PosLong.apply factory method is implemented in terms of a macro that checks literals for validity at compile time. Calling PosLong.apply with a literal Long value will either produce a valid PosLong instance at run time or an error at compile time. Here's an example:

    scala> import anyvals._
    import anyvals._
    
    scala> PosLong(1L)
    res0: org.scalactic.anyvals.PosLong = PosLong(1)
    
    scala> PosLong(0L)
    <console>:14: error: PosLong.apply can only be invoked on a positive (i > 0L) integer literal, like PosLong(42L).
                  PosLong(0L)
                         ^
    

    PosLong.apply cannot be used if the value being passed is a variable (i.e., not a literal), because the macro cannot determine the validity of variables at compile time (just literals). If you try to pass a variable to PosLong.apply, you'll get a compiler error that suggests you use a different factor method, PosLong.from, instead:

    scala> val x = 1L
    x: Long = 1
    
    scala> PosLong(x)
    <console>:15: error: PosLong.apply can only be invoked on an integer literal, like PosLong(42L). Please use PosLong.from instead.
                  PosLong(x)
                         ^
    

    The PosLong.from factory method will inspect the value at runtime and return an Option[PosLong]. If the value is valid, PosLong.from will return a Some[PosLong], else it will return a None. Here's an example:

    scala> PosLong.from(x)
    res3: Option[org.scalactic.anyvals.PosLong] = Some(PosLong(1))
    
    scala> val y = 0L
    y: Long = 0
    
    scala> PosLong.from(y)
    res4: Option[org.scalactic.anyvals.PosLong] = None
    

    The PosLong.apply factory method is marked implicit, so that you can pass literal Longs into methods that require PosLong, and get the same compile-time checking you get when calling PosLong.apply explicitly. Here's an example:

    scala> def invert(pos: PosLong): Long = Long.MaxValue - pos
    invert: (pos: org.scalactic.anyvals.PosLong)Long
    
    scala> invert(1L)
    res5: Long = 9223372036854775806
    
    scala> invert(Long.MaxValue)
    res6: Long = 0
    
    scala> invert(0L)
    <console>:15: error: PosLong.apply can only be invoked on a positive (i > 0L) integer literal, like PosLong(42L).
                  invert(0L)
                         ^
    
    scala> invert(-1L)
    <console>:15: error: PosLong.apply can only be invoked on a positive (i > 0L) integer literal, like PosLong(42L).
                  invert(-1L)
                          ^
    
    

    This example also demonstrates that the PosLong companion object also defines implicit widening conversions when either no loss of precision will occur or a similar conversion is provided in Scala. (For example, the implicit conversion from Long to Double in Scala can lose precision.) This makes it convenient to use a PosLong where a Long or wider type is needed. An example is the subtraction in the body of the invert method defined above, Long.MaxValue - pos. Although Long.MaxValue is a Long, which has no - method that takes a PosLong (the type of pos), you can still subtract pos, because the PosLong will be implicitly widened to Long.

  6. final class PosZDouble extends AnyVal

    Permalink

    An AnyVal for non-negative Doubles.

    An AnyVal for non-negative Doubles.

    Because PosZDouble is an AnyVal it will usually be as efficient as an Double, being boxed only when a Double would have been boxed.

    The PosZDouble.apply factory method is implemented in terms of a macro that checks literals for validity at compile time. Calling PosZDouble.apply with a literal Double value will either produce a valid PosZDouble instance at run time or an error at compile time. Here's an example:

    scala> import anyvals._
    import anyvals._
    
    scala> PosZDouble(1.1)
    res0: org.scalactic.anyvals.PosZDouble = PosZDouble(1.1)
    
    scala> PosZDouble(0.0)
    res1: org.scalactic.anyvals.PosZDouble = PosZDouble(0.0)
    
    scala> PosZDouble(-1.1)
    <console>:14: error: PosZDouble.apply can only be invoked on a non-negative (i >= 0.0) floating point literal, like PosZDouble(42.0).
                  PosZDouble(-1.1)
                            ^
    

    PosZDouble.apply cannot be used if the value being passed is a variable (i.e., not a literal), because the macro cannot determine the validity of variables at compile time (just literals). If you try to pass a variable to PosZDouble.apply, you'll get a compiler error that suggests you use a different factor method, PosZDouble.from, instead:

    scala> val x = 1.1
    x: Double = 1.1
    
    scala> PosZDouble(x)
    <console>:15: error: PosZDouble.apply can only be invoked on a floating point literal, like PosZDouble(42.0). Please use PosZDouble.from instead.
                  PosZDouble(x)
                            ^
    

    The PosZDouble.from factory method will inspect the value at runtime and return an Option[PosZDouble]. If the value is valid, PosZDouble.from will return a Some[PosZDouble], else it will return a None. Here's an example:

    scala> PosZDouble.from(x)
    res4: Option[org.scalactic.anyvals.PosZDouble] = Some(PosZDouble(1.1))
    
    scala> val y = -1.1
    y: Double = -1.1
    
    scala> PosZDouble.from(y)
    res5: Option[org.scalactic.anyvals.PosZDouble] = None
    

    The PosZDouble.apply factory method is marked implicit, so that you can pass literal Doubles into methods that require PosZDouble, and get the same compile-time checking you get when calling PosZDouble.apply explicitly. Here's an example:

    scala> def invert(pos: PosZDouble): Double = Double.MaxValue - pos
    invert: (pos: org.scalactic.anyvals.PosZDouble)Double
    
    scala> invert(0.0)
    res6: Double = 1.7976931348623157E308
    
    scala> invert(Double.MaxValue)
    res7: Double = 0.0
    
    scala> invert(-1.1)
    <console>:15: error: PosZDouble.apply can only be invoked on a non-negative (i >= 0.0) floating point literal, like PosZDouble(42.0).
                  invert(-1.1)
                          ^
    

    This example also demonstrates that the PosZDouble companion object also defines implicit widening conversions when a similar conversion is provided in Scala. This makes it convenient to use a PosZDouble where a Double or wider type is needed. An example is the subtraction in the body of the invert method defined above, Double.MaxValue - pos. Although Double.MaxValue is a Double, which has no - method that takes a PosZDouble (the type of pos), you can still subtract pos, because the PosZDouble will be implicitly widened to Double.

  7. final class PosZFloat extends AnyVal

    Permalink

    An AnyVal for non-negative Floats.

    An AnyVal for non-negative Floats.

    Because PosZFloat is an AnyVal it will usually be as efficient as an Float, being boxed only when a Float would have been boxed.

    The PosZFloat.apply factory method is implemented in terms of a macro that checks literals for validity at compile time. Calling PosZFloat.apply with a literal Float value will either produce a valid PosZFloat instance at run time or an error at compile time. Here's an example:

    scala> import anyvals._
    import anyvals._
    
    scala> PosZFloat(1.1F)
    res0: org.scalactic.anyvals.PosZFloat = PosZFloat(1.1)
    
    scala> PosZFloat(0.0F)
    res1: org.scalactic.anyvals.PosZFloat = PosZFloat(0.0)
    
    scala> PosZFloat(-1.1F)
    <console>:14: error: PosZFloat.apply can only be invoked on a non-negative (i >= 0.0F) floating point literal, like PosZFloat(42.0F).
                  PosZFloat(-1.1F)
                           ^
    

    PosZFloat.apply cannot be used if the value being passed is a variable (i.e., not a literal), because the macro cannot determine the validity of variables at compile time (just literals). If you try to pass a variable to PosZFloat.apply, you'll get a compiler error that suggests you use a different factor method, PosZFloat.from, instead:

    scala> val x = 1.1F
    x: Float = 1.1
    
    scala> PosZFloat(x)
    <console>:15: error: PosZFloat.apply can only be invoked on a floating point literal, like PosZFloat(42.0F). Please use PosZFloat.from instead.
                  PosZFloat(x)
                           ^
    

    The PosZFloat.from factory method will inspect the value at runtime and return an Option[PosZFloat]. If the value is valid, PosZFloat.from will return a Some[PosZFloat], else it will return a None. Here's an example:

    scala> PosZFloat.from(x)
    res4: Option[org.scalactic.anyvals.PosZFloat] = Some(PosZFloat(1.1))
    
    scala> val y = -1.1F
    y: Float = -1.1
    
    scala> PosZFloat.from(y)
    res5: Option[org.scalactic.anyvals.PosZFloat] = None
    

    The PosZFloat.apply factory method is marked implicit, so that you can pass literal Floats into methods that require PosZFloat, and get the same compile-time checking you get when calling PosZFloat.apply explicitly. Here's an example:

    scala> def invert(pos: PosZFloat): Float = Float.MaxValue - pos
    invert: (pos: org.scalactic.anyvals.PosZFloat)Float
    
    scala> invert(0.0F)
    res6: Float = 3.4028235E38
    
    scala> invert(Float.MaxValue)
    res7: Float = 0.0
    
    scala> invert(-1.1F)
    <console>:15: error: PosZFloat.apply can only be invoked on a non-negative (i >= 0.0F) floating point literal, like PosZFloat(42.0F).
                invert(-1.1F)
                        ^
    

    This example also demonstrates that the PosZFloat companion object also defines implicit widening conversions when a similar conversion is provided in Scala. This makes it convenient to use a PosZFloat where a Float or wider type is needed. An example is the subtraction in the body of the invert method defined above, Float.MaxValue - pos. Although Float.MaxValue is an Float, which has no - method that takes a PosZFloat (the type of pos), you can still subtract pos, because the PosZFloat will be implicitly widened to Float.

  8. final class PosZInt extends AnyVal

    Permalink

    An AnyVal for non-negative Ints.

    An AnyVal for non-negative Ints.

    Because PosZInt is an AnyVal it will usually be as efficient as an Int, being boxed only when an Int would have been boxed.

    The PosZInt.apply factory method is implemented in terms of a macro that checks literals for validity at compile time. Calling PosZInt.apply with a literal Int value will either produce a valid PosZInt instance at run time or an error at compile time. Here's an example:

    scala> import anyvals._
    import anyvals._
    
    scala> PosZInt(1)
    res0: org.scalactic.anyvals.PosZInt = PosZInt(1)
    
    scala> PosZInt(0)
    res1: org.scalactic.anyvals.PosZInt = PosZInt(0)
    
    scala> PosZInt(-1)
    <console>:14: error: PosZInt.apply can only be invoked on a non-negative (i >= 0) integer literal, like PosZInt(42).
                  PosZInt(-1)
                         ^
    

    PosZInt.apply cannot be used if the value being passed is a variable (i.e., not a literal), because the macro cannot determine the validity of variables at compile time (just literals). If you try to pass a variable to PosZInt.apply, you'll get a compiler error that suggests you use a different factor method, PosZInt.from, instead:

    scala> val x = 1
    x: Int = 1
    
    scala> PosZInt(x)
    <console>:15: error: PosZInt.apply can only be invoked on an integer literal, like PosZInt(42). Please use PosZInt.from instead.
                  PosZInt(x)
                         ^
    

    The PosZInt.from factory method will inspect the value at runtime and return an Option[PosZInt]. If the value is valid, PosZInt.from will return a Some[PosZInt], else it will return a None. Here's an example:

    scala> PosZInt.from(x)
    res4: Option[org.scalactic.anyvals.PosZInt] = Some(PosZInt(1))
    
    scala> val y = -1
    y: Int = -1
    
    scala> PosZInt.from(y)
    res5: Option[org.scalactic.anyvals.PosZInt] = None
    

    The PosZInt.apply factory method is marked implicit, so that you can pass literal Ints into methods that require PosZInt, and get the same compile-time checking you get when calling PosZInt.apply explicitly. Here's an example:

    scala> def invert(pos: PosZInt): Int = Int.MaxValue - pos
    invert: (pos: org.scalactic.anyvals.PosZInt)Int
    
    scala> invert(0)
    res7: Int = 2147483647
    
    scala> invert(Int.MaxValue)
    res8: Int = 0
    
    scala> invert(-1)
    <console>:15: error: PosZInt.apply can only be invoked on a non-negative (i >= 0) integer literal, like PosZInt(42).
                  invert(-1)
                          ^
    

    This example also demonstrates that the PosZInt companion object also defines implicit widening conversions when either no loss of precision will occur or a similar conversion is provided in Scala. (For example, the implicit conversion from Int to Float in Scala can lose precision.) This makes it convenient to use a PosZInt where an Int or wider type is needed. An example is the subtraction in the body of the invert method defined above, Int.MaxValue - pos. Although Int.MaxValue is an Int, which has no - method that takes a PosZInt (the type of pos), you can still subtract pos, because the PosZInt will be implicitly widened to Int.

  9. final class PosZLong extends AnyVal

    Permalink

    An AnyVal for non-negative Longs.

    An AnyVal for non-negative Longs.

    Because PosZLong is an AnyVal it will usually be as efficient as an Long, being boxed only when an Long would have been boxed.

    The PosZLong.apply factory method is implemented in terms of a macro that checks literals for validity at compile time. Calling PosZLong.apply with a literal Long value will either produce a valid PosZLong instance at run time or an error at compile time. Here's an example:

    scala> import anyvals._
    import anyvals._
    
    scala> PosZLong(1L)
    res0: org.scalactic.anyvals.PosZLong = PosZLong(1)
    
    scala> PosZLong(0L)
    res1: org.scalactic.anyvals.PosZLong = PosZLong(0)
    
    scala> PosZLong(-1L)
    <console>:14: error: PosZLong.apply can only be invoked on a non-negative (i >= 0L) integer literal, like PosZLong(42L).
                  PosZLong(-1L)
                          ^
    

    PosZLong.apply cannot be used if the value being passed is a variable (i.e., not a literal), because the macro cannot determine the validity of variables at compile time (just literals). If you try to pass a variable to PosZLong.apply, you'll get a compiler error that suggests you use a different factor method, PosZLong.from, instead:

    scala> val x = 1L
    x: Long = 1
    
    scala> PosZLong(x)
    <console>:15: error: PosZLong.apply can only be invoked on an integer literal, like PosZLong(42L). Please use PosZLong.from instead.
                  PosZLong(x)
                          ^
    

    The PosZLong.from factory method will inspect the value at runtime and return an Option[PosZLong]. If the value is valid, PosZLong.from will return a Some[PosZLong], else it will return a None. Here's an example:

    scala> PosZLong.from(x)
    res4: Option[org.scalactic.anyvals.PosZLong] = Some(PosZLong(1))
    
    scala> val y = -1L
    y: Long = -1
    
    scala> PosZLong.from(y)
    res5: Option[org.scalactic.anyvals.PosZLong] = None
    

    The PosZLong.apply factory method is marked implicit, so that you can pass literal Longs into methods that require PosZLong, and get the same compile-time checking you get when calling PosZLong.apply explicitly. Here's an example:

    scala> def invert(pos: PosZLong): Long = Long.MaxValue - pos
    invert: (pos: org.scalactic.anyvals.PosZLong)Long
    
    scala> invert(0L)
    res6: Long = 9223372036854775807
    
    scala> invert(Long.MaxValue)
    res7: Long = 0
    
    scala> invert(-1L)
    <console>:15: error: PosZLong.apply can only be invoked on a non-negative (i >= 0L) integer literal, like PosZLong(42L).
                  invert(-1L)
                          ^
    

    This example also demonstrates that the PosZLong companion object also defines implicit widening conversions when either no loss of precision will occur or a similar conversion is provided in Scala. (For example, the implicit conversion from Long to Double in Scala can lose precision.) This makes it convenient to use a PosZLong where a Long or wider type is needed. An example is the subtraction in the body of the invert method defined above, Long.MaxValue - pos. Although Long.MaxValue is a Long, which has no - method that takes a PosZLong (the type of pos), you can still subtract pos, because the PosZLong will be implicitly widened to Long.

Value Members

  1. object CompileTimeAssertions extends CompileTimeAssertions

    Permalink

    Companion object that facilitates the importing of CompileTimeAssertions members as an alternative to mixing in the trait.

    Companion object that facilitates the importing of CompileTimeAssertions members as an alternative to mixing in the trait.

  2. object PosDouble

    Permalink

    The companion object for PosDouble that offers factory methods that produce PosDoubles, implicit widening conversions from PosDouble to other numeric types, and maximum and minimum constant values for PosDouble.

    The companion object for PosDouble that offers factory methods that produce PosDoubles, implicit widening conversions from PosDouble to other numeric types, and maximum and minimum constant values for PosDouble.

  3. object PosFloat

    Permalink

    The companion object for PosFloat that offers factory methods that produce PosFloats, implicit widening conversions from PosFloat to other numeric types, and maximum and minimum constant values for PosFloat.

    The companion object for PosFloat that offers factory methods that produce PosFloats, implicit widening conversions from PosFloat to other numeric types, and maximum and minimum constant values for PosFloat.

  4. object PosInt

    Permalink

    The companion object for PosInt that offers factory methods that produce PosInts, implicit widening conversions from PosInt to other numeric types, and maximum and minimum constant values for PosInt.

    The companion object for PosInt that offers factory methods that produce PosInts, implicit widening conversions from PosInt to other numeric types, and maximum and minimum constant values for PosInt.

  5. object PosLong

    Permalink

    The companion object for PosLong that offers factory methods that produce PosLongs, implicit widening conversions from PosLong to other numeric types, and maximum and minimum constant values for PosLong.

    The companion object for PosLong that offers factory methods that produce PosLongs, implicit widening conversions from PosLong to other numeric types, and maximum and minimum constant values for PosLong.

  6. object PosZDouble

    Permalink

    The companion object for PosZDouble that offers factory methods that produce PosZDoubles, implicit widening conversions from PosZDouble to other numeric types, and maximum and minimum constant values for PosZDouble.

    The companion object for PosZDouble that offers factory methods that produce PosZDoubles, implicit widening conversions from PosZDouble to other numeric types, and maximum and minimum constant values for PosZDouble.

  7. object PosZFloat

    Permalink

    The companion object for PosZFloat that offers factory methods that produce PosZFloats, implicit widening conversions from PosZFloat to other numeric types, and maximum and minimum constant values for PosZFloat.

    The companion object for PosZFloat that offers factory methods that produce PosZFloats, implicit widening conversions from PosZFloat to other numeric types, and maximum and minimum constant values for PosZFloat.

  8. object PosZInt

    Permalink

    The companion object for PosZInt that offers factory methods that produce PosZInts, implicit widening conversions from PosZInt to other numeric types, and maximum and minimum constant values for PosZInt.

    The companion object for PosZInt that offers factory methods that produce PosZInts, implicit widening conversions from PosZInt to other numeric types, and maximum and minimum constant values for PosZInt.

  9. object PosZLong

    Permalink

    The companion object for PosZLong that offers factory methods that produce PosZLongs, implicit widening conversions from PosZLong to other numeric types, and maximum and minimum constant values for PosZLong.

    The companion object for PosZLong that offers factory methods that produce PosZLongs, implicit widening conversions from PosZLong to other numeric types, and maximum and minimum constant values for PosZLong.

Ungrouped