what to choose between require and assert in scala

Scala

Scala Problem Overview


Both require and assert are used to perform certain checks during runtime to verify certain conditions.

So what is the basic difference between them?

The only one I see is that require throws IllegalArgumentException and assert throws AssertionError.

How do I choose which one to use?

Scala Solutions


Solution 1 - Scala

As Kigyo mentioned there is a semantic difference

  • assert means that your program has reached an inconsistent state this might be a problem with the current method/function (I like to think of it a bit as HTTP 500 InternalServerError)
  • require means that the caller of the method is at fault and should fix its call (I like to think of it a bit as HTTP 400 BadRequest)

There is also a major technical difference:

assert is annotated with @elidable(ASSERTION) meaning you can compile your program with -Xelide-below ASSERTION or with -Xdisable-assertions and the compiler will not generate the bytecode for the assertions. This can significantly reduce bytecode size and improve performance if you have a large number of asserts.

Knowing this, you can use an assert to verify all the invariants everywhere in your program (all the preconditions/postconditions for every single method/function calls) and not pay the price in production.

You would usually have the "test" build with all the assertions enabled, it would be slower as it would verify all the assertions at all times, then you could have the "production" build of your product without the assertions, which you would eliminate all the internal state checks done through assertion

require is not elidable, it makes more sense for use in libraries (including internal libraries) to inform the caller of the preconditions to call a given method/function.

Solution 2 - Scala

This is only my subjective point of view.

I use require whenever I want a constraint on parameters.

As an example we can take the factorial for natural numbers. As we do not want to address negative numbers, we want to throw an IllegalArgumentException.

I would use assert, whenever you want to make sure some conditions (like invariants) are always true during execution. I see it as a way of testing.

Here is an example implementation of factorial with require and assert

def fac(i: Int) = {
  require(i >= 0, "i must be non negative") //this is for correct input

  @tailrec def loop(k: Int, result: Long = 1): Long = {
    assert(result == 1 || result >= k)   //this is only for verification

    if(k > 0) loop(k - 1, result * k) else result
  }

  loop(i)
}

When result > 1 is true, then the loop was executed at least once. So the result has to be bigger or equal to k. That would be a loop invariant.

When you are sure that your code is correct, you can remove the assert, but the require would stay.

Solution 3 - Scala

You can see here for a detailed discussion within Scala language.

I can add that, the key to distinguish between require and assert is to understand these two. These two are both tools of software quality but from different toolboxes of different paradigms. In summary assert is a Software testing tool which takes a corrective approach, whereas require is a design by contract tool which takes a preventive approach.

Both require and assert are means of controlling validity of state. Historically there were 2 distinct paradigms for dealing with invalid states. The first one which is mainstream collectively called software testing discipline methodologies and tools. The other, called design by contract. These are two paradigms which are not comparable.

Software testing ensures a code versatile enough to be capable of error prone actions, were not misused. Design by contract controls code from having such capability. In other words Software testing is corrective, and design by contract is preventive.

  • assert is used to write unit tests, i.e. if a method passes all tests each written by an assert expression, the code is qualified as error free. So assert seats besides operational code, and is an independent body.
  • require is embedded within code and part of it to assure nothing harmful can happen.

Solution 4 - Scala

In very simple language:

Require is used to enforce a precondition on the caller of a function or the creator of an object of some class. Whereas, assert is used to check the code of the function itself. So, if a precondition fails, then you get an illegal argument exception. Whereas, if an assertion fails and it's not the caller's fault and consequently you get an assertion error.

Solution 5 - Scala

require, ensure and invariance are concepts in Contract By Design (CBD) development process.

require checks for the pre-conditions that the caller should satisfy to consume the routine.

ensure checks for the correctness in the return value (and to also verify only the desired change has happened and nothing more)

invariance checks for the validness of the class at all critical times.

CBD is a development methodology to build correct/robust software. For more details on CBD Google and you should hit a link from Eiffel Software. Hope this helps.

Solution 6 - Scala

Scaladocs/javadocs are pretty good as well:

  • assert()

Tests an expression, throwing an AssertionError if false. Calls to this method will not be generated if -Xelide-below is greater than ASSERTION.

  • require()

Tests an expression, throwing an IllegalArgumentException if false. This method is similar to assert, but blames the caller of the method for violating the condition.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRoshanView Question on Stackoverflow
Solution 1 - ScalaJeanView Answer on Stackoverflow
Solution 2 - ScalaKigyoView Answer on Stackoverflow
Solution 3 - ScalashvahabiView Answer on Stackoverflow
Solution 4 - ScalaAnimesh SrivastavaView Answer on Stackoverflow
Solution 5 - ScalaSan DView Answer on Stackoverflow
Solution 6 - ScalaDonald DuckView Answer on Stackoverflow