Scala | Preconditions(assert, assume, require, ensuring)

Preconditions refer to some conditions in Scala that need to be fulfilled before going further with any code or program. In Scala, the process of Designing by Contract(DbC), a software designing process gives significance and meaning to Scala preconditions. The above approach was given by Betrand Mayer and it offers some post conditions and preconditions to a code block which if not satisfied, throws an exception.

Scala preconditions are a set of major functions that have different conditions a programmer must follow while designing a software. These functions come in Predef.scala package and one does not have to import any separate package.
The methods are :

  1. Assert – For general assertions
  2. Assume – Stating an Axiom
  3. Require – Specifically checking inputs
  4. Ensuring – is a post condition that has also been covered.
  • Assert

    Assert method puts a necessity for a condition to be satisfied while performing a certain action. If this condition is satisfied, then the code works fine, otherwise it throws an exception. The exceptions are checked at run time. The assert() method is thus a way to dynamically check the invariants. The above method takes a Boolean statement as a parameter and checks throughout the program if anywhere it is violated. it throws out an exception or an assertion error.

    Consider the following program as a part of Driver’s license approval of application process. It produces error if the applicant age is not equal to or more than 18.



    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // Code to check the age of the applicant
    val applicant_age = 16
      
    // assert method calling
    assert(applicant_age>17)

    chevron_right

    
    

    If the age is past the require minimum, the process is moved forward, otherwise, the program throws an Exception as below:

    Exception in thread "main" java.lang.AssertionError: assertion failed

    Looking up for the code for the same in Predef.scala, one would find a similar code like above:

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    def assert(assertion: Boolean) { 
      if (!assertion) 
        throw new java.lang.AssertionError("assertion failed"

    chevron_right

    
    

  • Assume

    Assume method is expected to be consumed by static analysis tools. It is supposed to limit down the number of conditions that have to be checked for execution of a program. If the assume condition is violated, the checker, silently leaves the path and doesn’t allow the program to go much deeper. The assume() method has the same syntax as the previously mentioned assert(), the only difference being its execution.

    The following example talks about a program that executes assuming that the age of the applicant is in any case greater than or equal to 18. The main code had been avoided and only the code containing the call to assume() is incorporated.

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // Code to check the age of the applicant
    license_approval(17)
      
    // Method to approve the License application
    def license_approval(applicant_age:Int) {
      
      assume(applicant_age>=18)
    //……………
    //…………
    //…………
    //The main code for checking the other details of the applicant. 
    //……………
    //…………
    //…………
    }

    chevron_right

    
    

    The assume() method gives the static checker an axiom that it could rely upon. This reduces the burden on the checker. The program runs deeper into the code if the Boolean condition of the assume() parameter is satisfied, otherwise, it throws an exception:

    Exception in thread "main" java.lang.AssertionError: assumption failed

    The similar code can be found inside the Predef.scala package:

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    def assume(assumption: Boolean) { 
      if (!assumption) 
        throw new java.lang.AssertionError("assumption failed"

    chevron_right

    
    

    While assert() is a method of asserting a condition in all execution paths or to check an invariant condition throughout the program, assume(), on the other hand, is used to reduce the load on the static analyser. It works locally to develop a divide-and-rule mechanism to help the analyzers to assume a condition and go through checking the code.

  • Require:

    This method has an innovative mode of dealing with the problem. It usually blames the method caller if a certain condition is not satisfied. If the condition is satisfied, the program goes on executing, if it does not, it throws an exception. The syntax is the same as before for assert() and assume() following a Boolean condition as the parameter. The working of the require() function can be shown with an example:
    The following example shown a method to double any odd number. If the number passed in the function is odd, it works smoothly, if not, then an exception is thrown.

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // Code to double the odd numbers
    def double_odd_numbers(number:Int) : Int = {
      
        require(number%2==1) // Checking if the number is odd using assume method
      
        number * 2;
      
    // Calling function
    double_odd_numbers(13)

    chevron_right

    
    

    If the condition is not satisfied, the following exception is thrown:

    Exception in thread "main" java.lang.IllegalArgumentException: requirement failed

    Looking up for the code for exception in Predef.scala, we come across the following code:

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    def require(requirement: Boolean) { 
      if (!requirement) 
        throw new IllegalArgumentException("requirement failed"

    chevron_right

    
    

  • Ensure:

    Ensure is a post-condition unlike the others. This method is usually applied along with the require() method to make a workable program. Considering the above example itself, we can modify the code by adding an ensure condition which requires the input number to be less than a certain limit.

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    // Code to double the odd numbers
    def double_odd_numbers(number:Int, lmt:Int) : Int = {
      
        require(number%2==1) // Checking if the number is odd using assume method
      
        number * 2;
      
    } ensuring(number * 2 < lmt) // Ensuring that the number produced is less than the limit. 
      
    // Calling function
    // The method also requires a limit [parameter to be passed. 
    double_odd_numbers(13, 100)

    chevron_right

    
    

    The assert() method thus requires that the checker must prove the condition that follows as a parameter, assume(), on the other hand, helps checker to reduce the burden by assuming that a certain condition holds true. While, the require() method specifies the condition that has to be followed by the caller of the function.

    If the programmer seeks to remove the exceptions generated by the assume() and assert() methods, one can use the -Xdisable-assertions command to do so.




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.


Article Tags :

Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.