#Newbie guard syntax question

2 messages · Page 1 of 1 (latest)

pure pine
#

I realize that the following issue might be trivial but I am not able to find anything online about this.
The following leap_year? is erroneous, apparently - my mix.exs file is complaining with weird errors I am not able to understand.

TL;DR: a trivial implementation such as the following

defmodule Year do
  @spec leap_year?(non_neg_integer()) :: boolean()
  def leap_year?(year) when rem(year, 400) == 0, do: true
  def leap_year?(year) when rem(year, 4) == 0 and not rem(year, 100) == 0, do: true
  def leap_year?(_), do: false
end

Throws the following at compile time error (on mix.exs):

    ** (MatchError) no match of right hand side value: {:erlang, :rem, 0}
        (elixir 1.15.7) lib/module/types.ex:218: Module.Types.format_warning/1
        (elixir 1.15.7) lib/module/parallel_checker.ex:310: anonymous fn/2 in Module.ParallelChecker.emit_warnings/2
        (elixir 1.15.7) lib/enum.ex:4317: Enum.flat_map_list/2
        (elixir 1.15.7) lib/module/parallel_checker.ex:267: Module.ParallelChecker.check_module/3
        (elixir 1.15.7) lib/module/parallel_checker.ex:82: anonymous fn/6 in Module.ParallelChecker.spawn/4Elixir
Kernel.defmodule(alias, do_block)```

If I remove the `not` clause in the pattern match above, the error disappears. So my workaround is to simply use a `!=` operator instead.

But... isn't this weird? What's going on?
coarse ledge
#

I think it is the order of operations. So the not is applied to the first item, not to the quantity. If you put the who thing in parens it should work: not (rem(year, 100) == 0)

For example, try this in iex:

bob = 5
bob == 5 # true
not bob == 5 #  (ArgumentError) argument error
not (bob == 5) # false

And worth noting - kinda peculiar to Elixir - the "not" operator can only be applied to booleans (unlike the !), so I cannot say "not bob" when bob isn't a boolean.