В чем смысл предположения в scala по сравнению с утверждением?
Scala, кажется, определяет 3 вида утверждений: assert
, require
и assume
.
Насколько я понимаю, разница (по сравнению с общим утверждением) require
заключается в том, что она специально предназначена для проверки входов (аргументов, входящих сообщений и т.д.). И каков смысл assume
then?
Ответы
Ответ 1
Если вы посмотрите на код в Predef.scala
, вы увидите, что все три выполняют очень похожее задание:
def assert(assertion: Boolean) {
if (!assertion)
throw new java.lang.AssertionError("assertion failed")
}
def assume(assumption: Boolean) {
if (!assumption)
throw new java.lang.AssertionError("assumption failed")
}
def require(requirement: Boolean) {
if (!requirement)
throw new IllegalArgumentException("requirement failed")
}
Существуют также версии, которые принимают дополнительные аргументы для целей отчетности (см. http://harrah.github.com/browse/samples/library/scala/Predef.scala.html).
Разница заключается в типе исключения, который они генерируют, и сообщении об ошибке, которое они генерируют.
Однако, статические шашки могли обрабатывать все три по-разному. Цель состоит в том, чтобы assert
указать условие, которое статическая проверка должна пытаться доказать, assume
должна использоваться для условия, которое может содержать проверочное устройство, а require
указывает условие, которое вызывающий должен обеспечить, Если статическая проверка обнаруживает нарушение assert
, она считает это ошибкой в коде, а при нарушении require
она предполагает, что вызывающий абонент неисправен.
Ответ 2
Разность
Разница между assert() и accept() заключается в том, что
- assert() - способ документировать и динамически проверять инварианты, а
- Предполагается, что() предназначено для использования инструментами статического анализа.
Предполагаемый потребитель/контекст assert() тестируется, например, тест Scala JUnit, а метод accept() - как средство спецификации дизайна по контракту до и после условий на функциях с намерением, чтобы эти спецификации могли потребляться инструментом статического анализа "(выдержка из scaladoc).
Статический анализ/проверка модели
В контексте статического анализа, как указал Адам Залчан, assert() - это утверждение всех путей выполнения, чтобы проверить глобальный инвариант, а предполагается() работает локально, чтобы уменьшить количество проверки того, что анализатор должен сделать. Предположим, что() используется в контексте предполагаемого-обоснованного рассуждения, которое является механизмом разделения и завоевания, чтобы помочь моделируемым шашкам принять что-то о методе, чтобы решить проблему государственного взрыва, возникающую при попытке проверить все пути, которые программа может занять. Например, если вы знали, что в дизайне вашей программы функция f1 (n1: Int, n2: Int) НИКОГДА не передается n2 < n1, то утверждение этого предположения явно помогло бы анализатору не проверять LOT комбинаций n1 и n2.
На практике
На практике, поскольку такие целые программные модели-шашки по-прежнему в основном теории, давайте посмотрим, что делает компилятор и интерпретатор Scala:
- выражения accept() и assert() проверяются во время выполнения
- -Xdisable-assertions отключает проверку assert() и assert()
Подробнее
Больше от превосходного scaladoc на эту тему:
утверждения
Набор функций assert
предоставляется для использования в качестве способа документирования и динамической проверки инвариантов в коде. утверждения assert можно отбросить во время выполнения, предоставив аргумент командной строки -Xdisable-assertions
команде scala
.
Также предлагаются варианты assert
, предназначенные для использования со средствами статического анализа: assume
, require
и ensuring
. require
и обеспечение предназначены для использования в качестве средства спецификации дизайна по контракту до и после условий для функций с намерением, чтобы эти спецификации могли потребляться инструментом статического анализа. Например,
def addNaturals(nats: List[Int]): Int = {
require(nats forall (_ >= 0), "List contains negative numbers")
nats.foldLeft(0)(_ + _)
} ensuring(_ >= 0)
Объявление addNaturals утверждает, что список прошедших целых чисел должен содержать только натуральные числа (т.е. неотрицательные), и возвращенный результат также будет естественным. require отличается от assert тем, что если условие терпит неудачу, тогда вызывающая функция виновата, а не логическая ошибка, сделанная внутри самих addNaturals. обеспечивает форму утверждения, объявляющую гарантию, предоставляемую функцией в отношении возвращаемого значения.
)
Ответ 3
I второй ответ Adams, вот только некоторые небольшие дополнения:
Когда assume
нарушается, инструмент проверки молчает путь, т.е. не будет следовать по пути глубже.
Следовательно, assume
часто используется для формулировки предварительных условий, assert
для формулировки пост-условий.
Эти концепции используются многими инструментами, например. инструмент анализа concolic KLEE, программные средства проверки ограниченной модели, такие как CBMC и LLBMC, а также частично статические инструменты анализа кода, основанные на абстрактной интерпретации. Статья Поиск общей основы: выберите, Assert, Предположите, вводит эти понятия и пытается их стандартизировать.