thojanssens1

thojanssens1

When to suffix a function by a bang!

Sometimes you have two versions for a function, one returning a tuple (ok or error tuple), and the other raising. The latter will be then have a bang ! suffix.

For example Map.fetch/2 and Map.fetch!/2

But not every function that raise will have the bang suffix. Random example: Ecto.Changeset.put_assoc/4.
If the given key is not found it will raise, but the function still has no bang !.

What is the rule as to when to adopt the bang for your functions and when not?

Most Liked

wolf4earth

wolf4earth

From my perspective a good rule of thumb is:

  • is there a non-raising version of the function?
  • is it a realistic scenario that the passed data might lead to a raised error?

Let’s inspect your examples with these rules.

Map.fetch!/2

  • is there a non-raising version of the function?
    Yes - Map.fetch/2
  • is it a realistic scenario that the passed data might lead to a raised error?
    Yes - as Map operates on maps, these might or might not contain the given key

Ecto.Changeset.put_assoc/4

  • is there a non-raising version of the function?
    No
  • is it a realistic scenario that the passed data might lead to a raised error?
    Noish - passing an invalid key is certainly a programmer error and should be caught as early as possible

So in that sense it makes sense that Map.fetch!/2 has a bang and Ecto.Changeset.put_assoc/4 has not.

christhekeele

christhekeele

Bangs in Elixir, as well as Ruby, are a way of indicating there is a similar, safer way to perform an operation. The intuition I’ve developed around them is:

  • When writing an API, present bang variants of functions for operations where both safe and unsafe versions have strong use-cases.

  • When choosing a variant, use the existence of the bang as an opportunity to ask yourself if you might really want the safer version.

  • When reading code with a bang variant, assume the author assessed the risk/failure modes in play, and chose the bang variant for some hopefully evident and important reason.

Not much more to it than that! It’s mostly a convention for developers to communicate a decision of caution and careful thought across time and space.

The only real rule is that there shouldn’t be a bang function without a non-bang equivalent. The bang doesn’t represent danger so much as an important decision made with intent, so it must be something that you decided to do in contrast to a more benign option.

Where Next?

Popular in Questions Top

senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
mgjohns61585
Could someone help me? I’m making my first elixir program, number guessing game. I can’t figure out how to convert the user’s guess from ...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: The documentation above suggests that while ...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call t...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New

Other popular topics Top

malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 42920 311
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
johnnyicon
Hi all, I’ve just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I’m trying to use Postgres...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 52341 488
New
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New

We're in Beta

About us Mission Statement