Using @assert in loop within function

Hi all,

I am trying to include @assert into my loop to make sure my results are correct.

I am trying to modify the error message:

row = 1
for i in 1:size(markets,1)
        equals_market(market::Int) = market == i
        dt_m = DataFrames.filter(:market_ids => equals_market, dt)
        k = size(dt_m,1)
        repl = replacement_threats_m(i, dt, nu_alpha, nu_p, nu_xj, nu_xm, nu_xr, marketsize, xi_no_draws)
        results[row:row+k-1,4] = replacements.best_replacer
        results[row:row+k-1,5] = replacements.profit_replacement
        @assert results[row:row+k-1,2:3] == Matrix{Float64}(replacements[!,1:2]) ["replacement_threats, not a proper merge, loop number is $i "]
    end

In the part [“replacement_threats, not a proper merge, loop number is i "] I am not totally sure how to call the loop iteration? "” only calls globals iirc? What would be the proper way to use information in the loop in the error message?

Thanks!

I don’t really understand what you mean by this. But anyway, interpolating the iteration counter with $i into the error message uses the local value of i

julia> for i in 1:3
       @assert i < 3 "$i >= 3"
       end
ERROR: AssertionError: 3 >= 3

What behavior have you experienced?

By the way, it’s not necessary to place the error message in [...]. It might look like that from the docstring

help?> @assert
  @assert cond [text]

  Throw an AssertionError if cond is false. Preferred syntax for writing assertions. Message text is optionally displayed upon assertion failure.

  │ Warning
  │
  │  An assert might be disabled at various optimization levels. Assert should therefore only be used as a debugging tool and not used for authentication verification (e.g., verifying passwords), nor should side
  │  effects needed for the function to work correctly be used inside of asserts.

but that just means that it is an optional argument.

Please heed the warning in the docstring though.

Also note, that you can write filter(:market_ids => ==(i), dt), or even dt[ dt.market_ids .==i, :]

1 Like

Also note this warning, you cannot rely on it, and it is not clear to me to which level it should be used at all, since debugging and producing are not exactly different in Julia.

If you really want that as a control to your data, I think you should use, for example,

i < 3 || error("$i must be smaller than 3")
1 Like

If I understand your code correctly than all of this

equals_market(market::Int) = market == i
dt_m = DataFrames.filter(:market_ids => equals_market, dt)
k = size(dt_m,1)

could be replaced by

k = sum(==(i), dt.market_ids)
1 Like

Thanks, yes you answered my question as regards calling the local “i”.

Also, thanks for the tips. Lastly, I see that @assert is then the wrong function for my purpose. I saw someone suggest

i < 3 || error("$i must be smaller than 3")

as an alternative. Do you use another?

Thanks, almost, i do need dt_m as it is an input in the function that I call in the loop. But yes, I can get rid of some lines. Thanks!

That’s a perfectly good solution.

1 Like