Guards! Guards

Lobsters Hottest News

Summary

An exploration of a surprising behavior in Elixir guards where the `is_map_key/2` guard can cause a guard failure instead of returning false, breaking the commutativity of boolean operators.

<p><a href="https://lobste.rs/s/b2emi7/guards_guards">Comments</a></p>
Original Article
View Cached Full Text

Cached at: 06/27/26, 05:55 PM

# Hauleth's blog - Guards! Guards! Source: [https://hauleth.dev/post/guards-guards/](https://hauleth.dev/post/guards-guards/) Let's start with simple quiz\. --- Given module defined as: ``` defmodule Foo do def a(x) when is_integer(x) or is_map_key(x, :foo), do: true def a(x), do: false def b(x) when is_map_key(x, :foo) or is_integer(x), do: true def b(x), do: false end ``` Try to answer these questions\. **Q:**What will be result of`Foo\.a\(%\{foo: 21\}\)`? `true` `false` WRONG RIGHT This one is straightforward\. We check guard, it has one condition`is\_integer\(x\) or is\_map\_key\(x, :foo\)`\. First one returns`false`, second returns`true`, Boolean's alternative results in`true`and first case is matched\. **Q:**What will be result of`Foo\.a\(37\)`? `true` `false` WRONG RIGHT This one is straightforward as well\. We check guard, it has one condition`is\_integer\(x\) or is\_map\_key\(x, :foo\)`\. First one returns`true`, second one isn't fired at all, because`or`operator is short circuiting\. **Q:**What will be result of`Foo\.b\(%\{foo: 21\}\)`? `true` `false` WRONG RIGHT Again, similar to the previous questions\. We check guard, it has one condition`is\_map\_key\(x, :foo\) or is\_integer\(x\)`\. First one returns`true`and the rest is short circuited\. **Q:**What will be result of`Foo\.b\(37\)`? `true` `false` WRONG RIGHT Ouch, something changed… Again, we check guard, one condition`is\_map\_key\(x, :foo\) or is\_integer\(x\)`\. We hit first clause`is\_map\_key\(x, :foo\)`and this**doesn't**return`false`, instead it fail\. Failure in one of guard functions isn't converted to`false`but instead makes whole guard expression fail\. This mean that`is\_integer\(x\)`part will**never**be called\. --- This behaviour is often surprising for a lot of Elixir developers, as it seemingly breaks commutative property of boolean operators\. However, to be honest, these never were commutative because of short circuiting\. It seems that Elixir at the time of writing \(Elixir 1\.20\.1, OTP 29\) do not warn about this issue\. ∎

Similar Articles

Guarded methods in OCaml

Lobsters Hottest

This article explains how to encode guarded methods in OCaml using type equality witnesses, allowing constraints on the receiver only for specific methods rather than the whole class.