Advertisement
mitrakov

Scala: assert vs. require

Feb 1st, 2018
275
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 4.30 KB | None | 0 0
  1. // 1. let's compare assert, assume, require, ensuring
  2. object Main extends App {
  3.   private val days = List("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")
  4.  
  5.   def printAllDays() {
  6.     assert(days.length == 7)           // usual assert (what we expect 100%), can be skipped in PROD
  7.     days foreach println               // for a static analysing tool, assert is a predicate to be proven
  8.   }
  9.  
  10.   def factorial(n: Long): Long = {
  11.     assume(n >= 0)                     // the same as assert, can be skipped in PROD
  12.     n match {                          // for a static analysing tool, assume is an axiom
  13.       case 0 => 1
  14.       case _ => n * factorial(n - 1)
  15.     }
  16.   }
  17.  
  18.   def getAverageAge(ages: Int*): Int = {
  19.     require(ages forall {_ >= 0})      // require from a caller that all ages must be non-negative! Checked in PROD!
  20.     ages match {
  21.       case Nil => 0
  22.       case _ => ages.sum / ages.length
  23.     }
  24.   } ensuring (result => result >= 0)   // ensure that everything is OK. Checked in PROD
  25.  
  26.  
  27.   printAllDays()
  28.   println(factorial(5))
  29.   println(getAverageAge(1, 2, 3, 4, 5))
  30. }
  31.  
  32. // Output:
  33. // Sunday
  34. // Monday
  35. // Tuesday
  36. // Wednesday
  37. // Thursday
  38. // Friday
  39. // Saturday
  40. // 120
  41. // 3
  42.  
  43.  
  44.  
  45. // 2. Now let's violate days:
  46. private val days = List("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "XYZ")
  47.  
  48. // Output:
  49. // Exception in thread "main" java.lang.AssertionError: assertion failed
  50. //  at scala.Predef$.assert(Predef.scala:204)
  51. //  at ru.mitrakov.self.sandbox.Main$.printAllDays(Main.scala:8)
  52.  
  53.  
  54.  
  55. // 3. Now let's violate factorial:
  56. assume(n >= 10)
  57.  
  58. // Output:
  59. // Sunday
  60. // Monday
  61. // Tuesday
  62. // Wednesday
  63. // Thursday
  64. // Friday
  65. // Saturday
  66. // Exception in thread "main" java.lang.AssertionError: assumption failed
  67. //  at scala.Predef$.assume(Predef.scala:235)
  68. //  at ru.mitrakov.self.sandbox.Main$.factorial(Main.scala:13)
  69.  
  70.  
  71.  
  72. // 4. Now let's pass incorrect parameters:
  73. println(getAverageAge(1, 2, 3, 4, 5, -1))
  74.  
  75. // Output:
  76. // Sunday
  77. // Monday
  78. // Tuesday
  79. // Wednesday
  80. // Thursday
  81. // Friday
  82. // Saturday
  83. // 120
  84. // Exception in thread "main" java.lang.IllegalArgumentException: requirement failed
  85. //  at scala.Predef$.require(Predef.scala:264)
  86. //  at ru.mitrakov.self.sandbox.Main$.getAverageAge(Main.scala:21)
  87.  
  88.  
  89.  
  90. // 5. Now let's change ensuring condition:
  91. } ensuring (result => result >= 10)
  92.  
  93. // Output:
  94. // Sunday
  95. // Monday
  96. // Tuesday
  97. // Wednesday
  98. // Thursday
  99. // Friday
  100. // Saturday
  101. // 120
  102. // Exception in thread "main" java.lang.AssertionError: assertion failed
  103. //  at scala.Predef$.assert(Predef.scala:204)
  104. //  at scala.Predef$Ensuring$.ensuring$extension2(Predef.scala:316)
  105. //  at ru.mitrakov.self.sandbox.Main$.getAverageAge(Main.scala:26)
  106.  
  107.  
  108.  
  109. // 6. Now let's violate both assert and assume:
  110. private val days = List("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "XYZ")
  111. ...
  112. assume(n >= 10)
  113. // Re-compile project with a compiler flag: -Xdisable-assertions
  114. // E.g. in IntelliJ IDEA:
  115. // Settings -> Build, Execution, Deployment -> Compiler -> Scala Compiler -> Additional compiler options
  116.  
  117. // Output:
  118. // Sunday
  119. // Monday
  120. // Tuesday
  121. // Wednesday
  122. // Thursday
  123. // Friday
  124. // Saturday
  125. // XYZ
  126. // 120
  127. // 3
  128.  
  129.  
  130.  
  131. // 7. But requirement will still be checked!
  132. println(getAverageAge(1, 2, 3, 4, 5, -1))
  133.  
  134. // Output:
  135. // Sunday
  136. // Monday
  137. // Tuesday
  138. // Wednesday
  139. // Thursday
  140. // Friday
  141. // Saturday
  142. // XYZ
  143. // 120
  144. // Exception in thread "main" java.lang.IllegalArgumentException: requirement failed
  145. //  at scala.Predef$.require(Predef.scala:264)
  146. //  at ru.mitrakov.self.sandbox.Main$.getAverageAge(Main.scala:21)
  147.  
  148.  
  149.  
  150. // 8. And 'ensuring' too! It may be confusing, because 'ensuring' is implemented
  151. // via 'assert', but it has NO '@elidable' annotation, so it will throw an exception!
  152. } ensuring (result => result >= 10)
  153.  
  154. // Output:
  155. // Sunday
  156. // Monday
  157. // Tuesday
  158. // Wednesday
  159. // Thursday
  160. // Friday
  161. // Saturday
  162. // XYZ
  163. // 120
  164. // Exception in thread "main" java.lang.AssertionError: assertion failed
  165. //  at scala.Predef$.assert(Predef.scala:204)
  166. //  at scala.Predef$Ensuring$.ensuring$extension2(Predef.scala:316)
  167. //  at ru.mitrakov.self.sandbox.Main$.getAverageAge(Main.scala:26)
  168.  
  169.  
  170.  
  171. // P.S. think of assert as InternalServerError (500), while of require - as BadRequest(400)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement