Should I use guard clauses in private functions?

I’m working on a basic credit card validator as a practice project for learning Elixir. After finishing a large chunk of my Validator module, I thought that I should go back through and make sure I guard clause some of the private functions I had written to ensure that they get used properly, which I had been doing for other private functions previously.

Thinking about it more now, however, I’m not sure whether this is actually necessary with private functions. If they can’t be called outside of the module, then I’m the one that’s controlling their use inside of the module — I know that they’re always being sent the right data in the right format.

I’m not sure which method is considered idiomatic Elixir. Should I add guard clauses to private functions anyways? Or are they unnecessary?

Guard clauses are typically used as an extension to pattern matching to separate distinct parts of logic over multiple function clauses belonging to the same function.

So whether or not a function is private really doesn’t come into it.

Your question suggests that you are using pattern matching/guards as some type of runtime type checking mechanism - but that’s not really what they are there for even if they can be used in that capacity.

I see. So if a private function doesn’t have multiple clauses that I need to distinguish, adding guard clauses may not be necessary — is that correct?

Generally speaking, yes.

Just keep in mind that if that function just wraps a case expression you could just turn it into a multi clause function.

1 Like

Sounds good. Thanks for the advice!

I sprinkle guards and pattern matched arguments about when I feel like I need protection against fat-fingering something but a @spec would be too noisy. If it’s public API surface, I’ll often do both.

If your benchmarks and profiles are showing these functions taking a lot of time, guards can also help the compiler, but wait until the benchmark tells you to, eh?

2 Likes

I use both pattern matching and guards as much as I can.

Erlang/Elixir do not have static type checking so you should try and catch problems at the compiler level as much as you can.

3 Likes