Как отключить @assert в Юлии - PullRequest
6 голосов
/ 09 октября 2019

Как старый программист на C, я использую множество утверждений в своем коде. Теперь я хочу глобально отключить их, чтобы ускорить процесс. Каков наилучший способ сделать это?

Ответы [ 3 ]

4 голосов
/ 09 октября 2019

Нет встроенного параметра / флага командной строки для отключения @assert s во всем мире, но (!).

На данный момент вы можете определить макрос @myassert, который, в зависимости от глобальногопереключатель, это неоперативный или обычный @assert:

asserting() = false # when set to true, this will enable all `@myassert`s

macro mayassert(test)
  esc(:(if $(@__MODULE__).asserting()
    @assert($test)
   end))
end

f(x) = @mayassert x < 2 

(взято из https://discourse.julialang.org/t/assert-alternatives/24775/14)

0 голосов
/ 11 октября 2019

Вы можете поместить свои операторы @assert в блок @debug. Затем вызов @assert деактивируется, если только вы не активируете отладку глобально (ENV["JULIA_DEBUG"] = "all") или только для вашего модуля (ENV["JULIA_DEBUG"] = "NameOfYourModule")

julia> @debug begin
          @assert 1==2
       end
       #or 
       @debug @assert 1==2 # assert is not called

julia> ENV["JULIA_DEBUG"] = "all" # enable debugging
"all"

julia> @debug begin
          @assert 1==2
       end
┌ Error: Exception while generating log record in module Main at REPL[4]:1
│   exception =
│    AssertionError: 1 == 2
│    Stacktrace:
│     [1] top-level scope at REPL[4]:2
│     [2] top-level scope at logging.jl:319
|     ...
└ @ Main REPL[4]:1
0 голосов
/ 09 октября 2019

Хотя было бы неплохо иметь эту функцию, потребность в @assert s в вашем коде может быть уменьшена путем определения и отправки для ваших собственных типов. Например, предположим, что у вас есть функция foo(t::TimeType) = t, но вы хотите принимать только времена, кратные пяти минутам. Вы можете создать новый тип с этим требованием:

using Dates

struct FiveMinuteMultiple
    t::DateTime

    function FiveMinuteMultiple(y, m, d, h, mi)
        if mi%5 != 0
            throw(DomainError(m, "the minute argument must be a multiple of 5"))
        end
        new(DateTime(y, m, d, h, mi))
    end
end

Теперь вы буквально не можете создать FiveMinuteMultiple, который не кратен пяти минутам:

julia> t = FiveMinuteMultiple(2016, 7, 15, 4, 23)
ERROR: DomainError with 7:
the minute argument must be a multiple of 5
Stacktrace:
 [1] FiveMinuteMultiple(::Int64, ::Int64, ::Int64, ::Int64, ::Int64) at ./REPL[2]:5
 [2] top-level scope at none:0

julia> t = FiveMinuteMultiple(2016, 7, 15, 4, 25)
FiveMinuteMultiple(2016-07-15T04:25:00)

Так что еслитеперь вы определяете foo(t::FiveMinuteMultiple) = t, вам больше не нужен @assert для проверки того, что аргумент - это время, кратное пяти минутам. Конечно, вам все равно придется оплачивать проверку аргументов при создании FiveMinuteMultiple, но, если это не горячий внутренний цикл, вам, возможно, понадобится дополнительная проверка данных в любом случае.

Преимущества:

  • Метод диспетчеризации гарантирует, что аргументы ваших функций имеют правильный тип.
  • Вы можете избежать дублирования одного и того же утверждения в нескольких функциях foo(t::FiveMinuteMultiple), bar(t::FiveMinuteMultiple) и baz(t::FiveMinuteMultiple).
  • Более конкретная аннотация аргумента предупреждает пользователей и разработчиков о том, что функция ожидает более специфический тип данных.

Недостатки:

  • В зависимости от вашего варианта использования вам может потребоваться перенаправить различные методы в поле данных в вашей структуре. Например, для FiveMinuteMultiple вам может потребоваться перенаправить такие методы, как day, hour и т. Д., В поле t структуры.
  • Добавление нового понятия (типа) для представленияутверждения о ваших данных могут привести к ненужному уровню абстракции.
...