package anyvals
- Alphabetic
- Public
- All
Type Members
-
trait
CompileTimeAssertions extends AnyRef
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
CompileTimeAssertionsis to make it easier to createAnyVals that restrict the values of types for which Scala supports literals:Int,Long,Float,Double,Char, andString. 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 oddIntis passed (as a precondition, and ensures an odd *Intis 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 anAnyValyou can avoid boxing theInt, 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
AnyValcannot have any constructor code, so to ensure that anyIntpassed to theOddIntconstructor is actually odd, the constructor must be private. That way the only way to construct a newOddIntis via theapplyfactory method in theOddIntcompanion object, which can require that the value be odd. This design eliminates the need for placingrequireandensuringclauses anywhere else that oddInts are needed, because the type promises the constraint. ThenextOddmethod 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.applyis passed anything besides an oddIntliteral. ClassOddIntwould 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
applymethod would be implemented in terms of a macro. Because theapplymethod will only work with literals, you'll need a second method that can work an any expression of typeInt. Although you could write a factory method that throws a runtime exception if a non-oddIntis passed, we recommend afrommethod that returns anOption. The returnedOptioncan 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
applymethod refers to a macro implementation method in classPosIntMacro. The macro implementation of any such method can look very similar to this one. The only changes you'd need to make is theisValidmethod 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
isValidmethod just takes the underlying type and returnstrueif it is valid, elsefalse. This method is placed here so the same valiation code can be used both in thefrommethod at runtime and theapplymacro at compile time. Theapplyactually does just two things. It calls aensureValidIntLiteral, performing a compile-time assertion that value passed toapplyis anIntliteral that is valid (in this case, odd). If the assertion fails,ensureValidIntLiteralwill 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,ensureValidIntLiteralwill 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 theOddInt.applyinvocation. We invoke the other factory method that returns anOption, and since we've proven at compile time that thatOptionwill be defined, we callgeton 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.
-
final
class
PosDouble extends AnyVal
An
AnyValfor positiveDoubles.An
AnyValfor positiveDoubles.Note: a
PosDoublemay not equal 0. If you want positive number or 0, use PosZDouble.Because
PosDoubleis anAnyValit will usually be as efficient as anDouble, being boxed only when aDoublewould have been boxed.The
PosDouble.applyfactory method is implemented in terms of a macro that checks literals for validity at compile time. CallingPosDouble.applywith a literalDoublevalue will either produce a validPosDoubleinstance 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.applycannot 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 toPosDouble.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.fromfactory method will inspect the value at runtime and return anOption[PosDouble]. If the value is valid,PosDouble.fromwill return aSome[PosDouble], else it will return aNone. 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.applyfactory method is marked implicit, so that you can pass literalDoubles into methods that requirePosDouble, and get the same compile-time checking you get when callingPosDouble.applyexplicitly. 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
PosDoublecompanion object also defines implicit widening conversions when a similar conversion is provided in Scala. This makes it convenient to use aPosDoublewhere aDoubleis needed. An example is the subtraction in the body of theinvertmethod defined above,Double.MaxValue - pos. AlthoughDouble.MaxValueis aDouble, which has no-method that takes aPosDouble(the type ofpos), you can still subtractpos, because thePosDoublewill be implicitly widened toDouble. -
final
class
PosFloat extends AnyVal
An
AnyValfor positiveFloats.An
AnyValfor positiveFloats.Note: a
PosFloatmay not equal 0. If you want positive number or 0, use PosZFloat.Because
PosFloatis anAnyValit will usually be as efficient as anFloat, being boxed only when anFloatwould have been boxed.The
PosFloat.applyfactory method is implemented in terms of a macro that checks literals for validity at compile time. CallingPosFloat.applywith a literalFloatvalue will either produce a validPosFloatinstance 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.applycannot 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 toPosFloat.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.fromfactory method will inspect the value at runtime and return anOption[PosFloat]. If the value is valid,PosFloat.fromwill return aSome[PosFloat], else it will return aNone. 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.applyfactory method is marked implicit, so that you can pass literalFloats into methods that requirePosFloat, and get the same compile-time checking you get when callingPosFloat.applyexplicitly. 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
PosFloatcompanion object also defines implicit widening conversions when no loss of precision will occur. This makes it convenient to use aPosFloatwhere aFloator wider type is needed. An example is the subtraction in the body of theinvertmethod defined above,Float.MaxValue - pos. AlthoughFloat.MaxValueis aFloat, which has no-method that takes aPosFloat(the type ofpos), you can still subtractpos, because thePosFloatwill be implicitly widened toFloat. -
final
class
PosInt extends AnyVal
An
AnyValfor positiveInts.An
AnyValfor positiveInts.Note: a
PosIntmay not equal 0. If you want positive number or 0, use PosZInt.Because
PosIntis anAnyValit will usually be as efficient as anInt, being boxed only when anIntwould have been boxed.The
PosInt.applyfactory method is implemented in terms of a macro that checks literals for validity at compile time. CallingPosInt.applywith a literalIntvalue will either produce a validPosIntinstance 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.applycannot 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 toPosInt.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.fromfactory method will inspect the value at runtime and return anOption[PosInt]. If the value is valid,PosInt.fromwill return aSome[PosInt], else it will return aNone. 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.applyfactory method is marked implicit, so that you can pass literalInts into methods that requirePosInt, and get the same compile-time checking you get when callingPosInt.applyexplicitly. 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
PosIntcompanion 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 fromIntto Float in Scala can lose precision.) This makes it convenient to use aPosIntwhere anIntor wider type is needed. An example is the subtraction in the body of theinvertmethod defined above,Int.MaxValue - pos. AlthoughInt.MaxValueis anInt, which has no-method that takes aPosInt(the type ofpos), you can still subtractpos, because thePosIntwill be implicitly widened toInt. -
final
class
PosLong extends AnyVal
An
AnyValfor positiveLongs.An
AnyValfor positiveLongs.Note: a
PosLongmay not equal 0. If you want positive number or 0, use PosZLong.Because
PosLongis anAnyValit will usually be as efficient as anLong, being boxed only when anLongwould have been boxed.The
PosLong.applyfactory method is implemented in terms of a macro that checks literals for validity at compile time. CallingPosLong.applywith a literalLongvalue will either produce a validPosLonginstance 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.applycannot 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 toPosLong.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.fromfactory method will inspect the value at runtime and return anOption[PosLong]. If the value is valid,PosLong.fromwill return aSome[PosLong], else it will return aNone. 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.applyfactory method is marked implicit, so that you can pass literalLongs into methods that requirePosLong, and get the same compile-time checking you get when callingPosLong.applyexplicitly. 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
PosLongcompanion 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 fromLongto Double in Scala can lose precision.) This makes it convenient to use aPosLongwhere aLongor wider type is needed. An example is the subtraction in the body of theinvertmethod defined above,Long.MaxValue - pos. AlthoughLong.MaxValueis aLong, which has no-method that takes aPosLong(the type ofpos), you can still subtractpos, because thePosLongwill be implicitly widened toLong. -
final
class
PosZDouble extends AnyVal
An
AnyValfor non-negativeDoubles.An
AnyValfor non-negativeDoubles.Because
PosZDoubleis anAnyValit will usually be as efficient as anDouble, being boxed only when aDoublewould have been boxed.The
PosZDouble.applyfactory method is implemented in terms of a macro that checks literals for validity at compile time. CallingPosZDouble.applywith a literalDoublevalue will either produce a validPosZDoubleinstance 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.applycannot 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 toPosZDouble.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.fromfactory method will inspect the value at runtime and return anOption[PosZDouble]. If the value is valid,PosZDouble.fromwill return aSome[PosZDouble], else it will return aNone. 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.applyfactory method is marked implicit, so that you can pass literalDoubles into methods that requirePosZDouble, and get the same compile-time checking you get when callingPosZDouble.applyexplicitly. 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
PosZDoublecompanion object also defines implicit widening conversions when a similar conversion is provided in Scala. This makes it convenient to use aPosZDoublewhere aDoubleor wider type is needed. An example is the subtraction in the body of theinvertmethod defined above,Double.MaxValue - pos. AlthoughDouble.MaxValueis aDouble, which has no-method that takes aPosZDouble(the type ofpos), you can still subtractpos, because thePosZDoublewill be implicitly widened toDouble. -
final
class
PosZFloat extends AnyVal
An
AnyValfor non-negativeFloats.An
AnyValfor non-negativeFloats.Because
PosZFloatis anAnyValit will usually be as efficient as anFloat, being boxed only when aFloatwould have been boxed.The
PosZFloat.applyfactory method is implemented in terms of a macro that checks literals for validity at compile time. CallingPosZFloat.applywith a literalFloatvalue will either produce a validPosZFloatinstance 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.applycannot 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 toPosZFloat.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.fromfactory method will inspect the value at runtime and return anOption[PosZFloat]. If the value is valid,PosZFloat.fromwill return aSome[PosZFloat], else it will return aNone. 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.applyfactory method is marked implicit, so that you can pass literalFloats into methods that requirePosZFloat, and get the same compile-time checking you get when callingPosZFloat.applyexplicitly. 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
PosZFloatcompanion object also defines implicit widening conversions when a similar conversion is provided in Scala. This makes it convenient to use aPosZFloatwhere aFloator wider type is needed. An example is the subtraction in the body of theinvertmethod defined above,Float.MaxValue - pos. AlthoughFloat.MaxValueis anFloat, which has no-method that takes aPosZFloat(the type ofpos), you can still subtractpos, because thePosZFloatwill be implicitly widened toFloat. -
final
class
PosZInt extends AnyVal
An
AnyValfor non-negativeInts.An
AnyValfor non-negativeInts.Because
PosZIntis anAnyValit will usually be as efficient as anInt, being boxed only when anIntwould have been boxed.The
PosZInt.applyfactory method is implemented in terms of a macro that checks literals for validity at compile time. CallingPosZInt.applywith a literalIntvalue will either produce a validPosZIntinstance 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.applycannot 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 toPosZInt.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.fromfactory method will inspect the value at runtime and return anOption[PosZInt]. If the value is valid,PosZInt.fromwill return aSome[PosZInt], else it will return aNone. 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.applyfactory method is marked implicit, so that you can pass literalInts into methods that requirePosZInt, and get the same compile-time checking you get when callingPosZInt.applyexplicitly. 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
PosZIntcompanion 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 fromIntto Float in Scala can lose precision.) This makes it convenient to use aPosZIntwhere anIntor wider type is needed. An example is the subtraction in the body of theinvertmethod defined above,Int.MaxValue - pos. AlthoughInt.MaxValueis anInt, which has no-method that takes aPosZInt(the type ofpos), you can still subtractpos, because thePosZIntwill be implicitly widened toInt. -
final
class
PosZLong extends AnyVal
An
AnyValfor non-negativeLongs.An
AnyValfor non-negativeLongs.Because
PosZLongis anAnyValit will usually be as efficient as anLong, being boxed only when anLongwould have been boxed.The
PosZLong.applyfactory method is implemented in terms of a macro that checks literals for validity at compile time. CallingPosZLong.applywith a literalLongvalue will either produce a validPosZLonginstance 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.applycannot 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 toPosZLong.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.fromfactory method will inspect the value at runtime and return anOption[PosZLong]. If the value is valid,PosZLong.fromwill return aSome[PosZLong], else it will return aNone. 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.applyfactory method is marked implicit, so that you can pass literalLongs into methods that requirePosZLong, and get the same compile-time checking you get when callingPosZLong.applyexplicitly. 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
PosZLongcompanion 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 fromLongto Double in Scala can lose precision.) This makes it convenient to use aPosZLongwhere aLongor wider type is needed. An example is the subtraction in the body of theinvertmethod defined above,Long.MaxValue - pos. AlthoughLong.MaxValueis aLong, which has no-method that takes aPosZLong(the type ofpos), you can still subtractpos, because thePosZLongwill be implicitly widened toLong.
Value Members
-
object
CompileTimeAssertions extends CompileTimeAssertions
Companion object that facilitates the importing of
CompileTimeAssertionsmembers as an alternative to mixing in the trait. -
object
PosDouble
The companion object for
PosDoublethat offers factory methods that producePosDoubles, implicit widening conversions fromPosDoubleto other numeric types, and maximum and minimum constant values forPosDouble. -
object
PosFloat
The companion object for
PosFloatthat offers factory methods that producePosFloats, implicit widening conversions fromPosFloatto other numeric types, and maximum and minimum constant values forPosFloat. -
object
PosInt
The companion object for
PosIntthat offers factory methods that producePosInts, implicit widening conversions fromPosIntto other numeric types, and maximum and minimum constant values forPosInt. -
object
PosLong
The companion object for
PosLongthat offers factory methods that producePosLongs, implicit widening conversions fromPosLongto other numeric types, and maximum and minimum constant values forPosLong. -
object
PosZDouble
The companion object for
PosZDoublethat offers factory methods that producePosZDoubles, implicit widening conversions fromPosZDoubleto other numeric types, and maximum and minimum constant values forPosZDouble. -
object
PosZFloat
The companion object for
PosZFloatthat offers factory methods that producePosZFloats, implicit widening conversions fromPosZFloatto other numeric types, and maximum and minimum constant values forPosZFloat. -
object
PosZInt
The companion object for
PosZIntthat offers factory methods that producePosZInts, implicit widening conversions fromPosZIntto other numeric types, and maximum and minimum constant values forPosZInt. -
object
PosZLong
The companion object for
PosZLongthat offers factory methods that producePosZLongs, implicit widening conversions fromPosZLongto other numeric types, and maximum and minimum constant values forPosZLong.