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
CompileTimeAssertions
is to make it easier to createAnyVal
s 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 oddInt
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 anAnyVal
you 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
AnyVal
cannot have any constructor code, so to ensure that anyInt
passed to theOddInt
constructor is actually odd, the constructor must be private. That way the only way to construct a newOddInt
is via theapply
factory method in theOddInt
companion object, which can require that the value be odd. This design eliminates the need for placingrequire
andensuring
clauses anywhere else that oddInt
s are needed, because the type promises the constraint. ThenextOdd
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 oddInt
literal. ClassOddInt
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 theapply
method 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-oddInt
is passed, we recommend afrom
method that returns anOption
. The returnedOption
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 classPosIntMacro
. The macro implementation of any such method can look very similar to this one. The only changes you'd need to make is theisValid
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 returnstrue
if it is valid, elsefalse
. This method is placed here so the same valiation code can be used both in thefrom
method at runtime and theapply
macro at compile time. Theapply
actually does just two things. It calls aensureValidIntLiteral
, performing a compile-time assertion that value passed toapply
is anInt
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 theOddInt.apply
invocation. We invoke the other factory method that returns anOption
, and since we've proven at compile time that thatOption
will be defined, we callget
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.
-
final
class
PosDouble extends AnyVal
An
AnyVal
for positiveDouble
s.An
AnyVal
for positiveDouble
s.Note: a
PosDouble
may not equal 0. If you want positive number or 0, use PosZDouble.Because
PosDouble
is anAnyVal
it will usually be as efficient as anDouble
, being boxed only when aDouble
would have been boxed.The
PosDouble.apply
factory method is implemented in terms of a macro that checks literals for validity at compile time. CallingPosDouble.apply
with a literalDouble
value will either produce a validPosDouble
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 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.from
factory method will inspect the value at runtime and return anOption[PosDouble]
. If the value is valid,PosDouble.from
will 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.apply
factory method is marked implicit, so that you can pass literalDouble
s into methods that requirePosDouble
, and get the same compile-time checking you get when callingPosDouble.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 aPosDouble
where aDouble
is needed. An example is the subtraction in the body of theinvert
method defined above,Double.MaxValue - pos
. AlthoughDouble.MaxValue
is aDouble
, which has no-
method that takes aPosDouble
(the type ofpos
), you can still subtractpos
, because thePosDouble
will be implicitly widened toDouble
. -
final
class
PosFloat extends AnyVal
An
AnyVal
for positiveFloat
s.An
AnyVal
for positiveFloat
s.Note: a
PosFloat
may not equal 0. If you want positive number or 0, use PosZFloat.Because
PosFloat
is anAnyVal
it will usually be as efficient as anFloat
, being boxed only when anFloat
would have been boxed.The
PosFloat.apply
factory method is implemented in terms of a macro that checks literals for validity at compile time. CallingPosFloat.apply
with a literalFloat
value will either produce a validPosFloat
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 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.from
factory method will inspect the value at runtime and return anOption[PosFloat]
. If the value is valid,PosFloat.from
will 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.apply
factory method is marked implicit, so that you can pass literalFloat
s into methods that requirePosFloat
, and get the same compile-time checking you get when callingPosFloat.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 aPosFloat
where aFloat
or wider type is needed. An example is the subtraction in the body of theinvert
method defined above,Float.MaxValue - pos
. AlthoughFloat.MaxValue
is aFloat
, which has no-
method that takes aPosFloat
(the type ofpos
), you can still subtractpos
, because thePosFloat
will be implicitly widened toFloat
. -
final
class
PosInt extends AnyVal
An
AnyVal
for positiveInt
s.An
AnyVal
for positiveInt
s.Note: a
PosInt
may not equal 0. If you want positive number or 0, use PosZInt.Because
PosInt
is anAnyVal
it will usually be as efficient as anInt
, being boxed only when anInt
would have been boxed.The
PosInt.apply
factory method is implemented in terms of a macro that checks literals for validity at compile time. CallingPosInt.apply
with a literalInt
value will either produce a validPosInt
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 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.from
factory method will inspect the value at runtime and return anOption[PosInt]
. If the value is valid,PosInt.from
will 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.apply
factory method is marked implicit, so that you can pass literalInt
s into methods that requirePosInt
, and get the same compile-time checking you get when callingPosInt.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 fromInt
to Float in Scala can lose precision.) This makes it convenient to use aPosInt
where anInt
or wider type is needed. An example is the subtraction in the body of theinvert
method defined above,Int.MaxValue - pos
. AlthoughInt.MaxValue
is anInt
, which has no-
method that takes aPosInt
(the type ofpos
), you can still subtractpos
, because thePosInt
will be implicitly widened toInt
. -
final
class
PosLong extends AnyVal
An
AnyVal
for positiveLong
s.An
AnyVal
for positiveLong
s.Note: a
PosLong
may not equal 0. If you want positive number or 0, use PosZLong.Because
PosLong
is anAnyVal
it will usually be as efficient as anLong
, being boxed only when anLong
would have been boxed.The
PosLong.apply
factory method is implemented in terms of a macro that checks literals for validity at compile time. CallingPosLong.apply
with a literalLong
value will either produce a validPosLong
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 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.from
factory method will inspect the value at runtime and return anOption[PosLong]
. If the value is valid,PosLong.from
will 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.apply
factory method is marked implicit, so that you can pass literalLong
s into methods that requirePosLong
, and get the same compile-time checking you get when callingPosLong.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 fromLong
to Double in Scala can lose precision.) This makes it convenient to use aPosLong
where aLong
or wider type is needed. An example is the subtraction in the body of theinvert
method defined above,Long.MaxValue - pos
. AlthoughLong.MaxValue
is aLong
, which has no-
method that takes aPosLong
(the type ofpos
), you can still subtractpos
, because thePosLong
will be implicitly widened toLong
. -
final
class
PosZDouble extends AnyVal
An
AnyVal
for non-negativeDouble
s.An
AnyVal
for non-negativeDouble
s.Because
PosZDouble
is anAnyVal
it will usually be as efficient as anDouble
, being boxed only when aDouble
would have been boxed.The
PosZDouble.apply
factory method is implemented in terms of a macro that checks literals for validity at compile time. CallingPosZDouble.apply
with a literalDouble
value will either produce a validPosZDouble
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 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.from
factory method will inspect the value at runtime and return anOption[PosZDouble]
. If the value is valid,PosZDouble.from
will 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.apply
factory method is marked implicit, so that you can pass literalDouble
s into methods that requirePosZDouble
, and get the same compile-time checking you get when callingPosZDouble.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 aPosZDouble
where aDouble
or wider type is needed. An example is the subtraction in the body of theinvert
method defined above,Double.MaxValue - pos
. AlthoughDouble.MaxValue
is aDouble
, which has no-
method that takes aPosZDouble
(the type ofpos
), you can still subtractpos
, because thePosZDouble
will be implicitly widened toDouble
. -
final
class
PosZFloat extends AnyVal
An
AnyVal
for non-negativeFloat
s.An
AnyVal
for non-negativeFloat
s.Because
PosZFloat
is anAnyVal
it will usually be as efficient as anFloat
, being boxed only when aFloat
would have been boxed.The
PosZFloat.apply
factory method is implemented in terms of a macro that checks literals for validity at compile time. CallingPosZFloat.apply
with a literalFloat
value will either produce a validPosZFloat
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 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.from
factory method will inspect the value at runtime and return anOption[PosZFloat]
. If the value is valid,PosZFloat.from
will 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.apply
factory method is marked implicit, so that you can pass literalFloat
s into methods that requirePosZFloat
, and get the same compile-time checking you get when callingPosZFloat.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 aPosZFloat
where aFloat
or wider type is needed. An example is the subtraction in the body of theinvert
method defined above,Float.MaxValue - pos
. AlthoughFloat.MaxValue
is anFloat
, which has no-
method that takes aPosZFloat
(the type ofpos
), you can still subtractpos
, because thePosZFloat
will be implicitly widened toFloat
. -
final
class
PosZInt extends AnyVal
An
AnyVal
for non-negativeInt
s.An
AnyVal
for non-negativeInt
s.Because
PosZInt
is anAnyVal
it will usually be as efficient as anInt
, being boxed only when anInt
would have been boxed.The
PosZInt.apply
factory method is implemented in terms of a macro that checks literals for validity at compile time. CallingPosZInt.apply
with a literalInt
value will either produce a validPosZInt
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 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.from
factory method will inspect the value at runtime and return anOption[PosZInt]
. If the value is valid,PosZInt.from
will 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.apply
factory method is marked implicit, so that you can pass literalInt
s into methods that requirePosZInt
, and get the same compile-time checking you get when callingPosZInt.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 fromInt
to Float in Scala can lose precision.) This makes it convenient to use aPosZInt
where anInt
or wider type is needed. An example is the subtraction in the body of theinvert
method defined above,Int.MaxValue - pos
. AlthoughInt.MaxValue
is anInt
, which has no-
method that takes aPosZInt
(the type ofpos
), you can still subtractpos
, because thePosZInt
will be implicitly widened toInt
. -
final
class
PosZLong extends AnyVal
An
AnyVal
for non-negativeLong
s.An
AnyVal
for non-negativeLong
s.Because
PosZLong
is anAnyVal
it will usually be as efficient as anLong
, being boxed only when anLong
would have been boxed.The
PosZLong.apply
factory method is implemented in terms of a macro that checks literals for validity at compile time. CallingPosZLong.apply
with a literalLong
value will either produce a validPosZLong
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 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.from
factory method will inspect the value at runtime and return anOption[PosZLong]
. If the value is valid,PosZLong.from
will 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.apply
factory method is marked implicit, so that you can pass literalLong
s into methods that requirePosZLong
, and get the same compile-time checking you get when callingPosZLong.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 fromLong
to Double in Scala can lose precision.) This makes it convenient to use aPosZLong
where aLong
or wider type is needed. An example is the subtraction in the body of theinvert
method defined above,Long.MaxValue - pos
. AlthoughLong.MaxValue
is aLong
, which has no-
method that takes aPosZLong
(the type ofpos
), you can still subtractpos
, because thePosZLong
will be implicitly widened toLong
.
Value Members
-
object
CompileTimeAssertions extends CompileTimeAssertions
Companion object that facilitates the importing of
CompileTimeAssertions
members as an alternative to mixing in the trait. -
object
PosDouble
The companion object for
PosDouble
that offers factory methods that producePosDouble
s, implicit widening conversions fromPosDouble
to other numeric types, and maximum and minimum constant values forPosDouble
. -
object
PosFloat
The companion object for
PosFloat
that offers factory methods that producePosFloat
s, implicit widening conversions fromPosFloat
to other numeric types, and maximum and minimum constant values forPosFloat
. -
object
PosInt
The companion object for
PosInt
that offers factory methods that producePosInt
s, implicit widening conversions fromPosInt
to other numeric types, and maximum and minimum constant values forPosInt
. -
object
PosLong
The companion object for
PosLong
that offers factory methods that producePosLong
s, implicit widening conversions fromPosLong
to other numeric types, and maximum and minimum constant values forPosLong
. -
object
PosZDouble
The companion object for
PosZDouble
that offers factory methods that producePosZDouble
s, implicit widening conversions fromPosZDouble
to other numeric types, and maximum and minimum constant values forPosZDouble
. -
object
PosZFloat
The companion object for
PosZFloat
that offers factory methods that producePosZFloat
s, implicit widening conversions fromPosZFloat
to other numeric types, and maximum and minimum constant values forPosZFloat
. -
object
PosZInt
The companion object for
PosZInt
that offers factory methods that producePosZInt
s, implicit widening conversions fromPosZInt
to other numeric types, and maximum and minimum constant values forPosZInt
. -
object
PosZLong
The companion object for
PosZLong
that offers factory methods that producePosZLong
s, implicit widening conversions fromPosZLong
to other numeric types, and maximum and minimum constant values forPosZLong
.