gameline
Hi,
I was surprised I couldn’t find any argument on this on the net so here I am.
When you make recursive function that deal with list and want to pattern match argument against [] or [head|tail] you can:
function [], do: *something*
function [h|t], do: *something else*
which is what I would call the Elixir way. A more haskellish way might be:
function argument do
case argument []
[] -> something()
[h|t] -> something_else()
end
end
The first option allow you to handle different arities the same way but is there other good arguments on why you should use the first option instead of the second ?
Trending in Questions
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
Documentation
While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
Hello,
I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind.
However, when I launch mix phx.server, I get an error...
New
Hi everyone,
I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding.
I sta...
New
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
I’m working on a small exercise involving update_in/3, and I came up with this solution:
data = %{
name: "Periodic Table",
category:...
New
I’ve got trouble wrapping my head around the order in which functions are called in this snippet (from Phoenix’s authentication):
toke...
New
Other Trending Topics
Edit: 2026 May 15 - This post is archived.
Mob is alive!!
Main docs: mob v0.7.11 — Documentation
A bit of explanation for the slightly c...
New
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
Hobbes is a low-level distributed database for the Elixir programming language.
Hobbes provides a simple, safe, and scalable storage lay...
New
Hi everyone!
The first release candidate for the Expert language server project is now available!
We’ve published a press release detai...
New
A little off-topic, but I feel like people here have a good head on their shoulders.
I used to be quite good at making software. Was luc...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ai
- #ecto-query
- #elixirconf-us
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #elixirconf-eu
- #api
- #forms
- #metaprogramming
- #hex











Showing Posts 15 to 6- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
rvirding
It makes no difference at all with regards to efficiency. Literally the complier translates it into almost the same code with the main difference being what error you will get.
dimitarvp
I am aware, thank you. We have the right to disagree with some of them.
As suggested above, I’d nest the deconstruction of a more complex piece of data, meaning I’d do a partial reconstruction at the top-level function(s) and then pass parts of it to nested ones where they also reconstruct. Huge deconstruction heads indeed are not easy to visually parse sometimes.
Cool, I disagree with that one too.
IloSophiep
I just want to mention that I think what you are “calling smelly” is actually the preferred refactoring for one of the anti-patterns in the Elixir documentation: Complex extractions in clauses. It might be worth thinking about it once more and weighing off the pros and cons. At least for me it was something that looked like a weird recommendation at first, but I started liking it. But maybe I misunderstood your point completely…
Edit: I just realized that’s pretty much what @JohnnyCurran already stated with
dimitarvp
Nah, not saying that, I am saying that
FunctionClauseErroris a symptom of a very early stage problem. Hence, having everything be in the function header is a non-issue for me.As for them growing big, yes, I can see that. But I would rework that into smaller functions e.g. in your example I would pass
attrsto sub-functions.Not at all, these are genuine ergonomics that can and have tripped people – myself included – so it’s worth debating especially if we end up in the same team.
JohnnyCurran
I understand and I do empathize. I often find myself wanting to unwrap everything in the function head. I’ve found, however, after over 4 years of production elixir, that it causes more problems than it solves
in particular, how do you square:
with:
At a certain point, especially on a team, the sizes of parameters are going to get large. It’s inevitable. is it all-or-nothing, or is it a manageable size?
And, to be honest I’m not sure I totally understand this question:
If you are suggesting we all write error-free code, I agree, but I don’t know how practical that is. FunctionClauseErrors aren’t exclusive to third-party apis, and, like everything in software – things change. To suggest “just don’t write code that throws a FunctionClauseError” seems misled
In any case – I have genuinely enjoyed this discussion with you as I love discussing the ins-and-outs of Elixir with whoever is unfortunate enough to be within earshot
, especially so with those whom which I disagree. There is no growth without disagreement. All that to say that I hope my tone has not come off as disrespectful which I know it has the possibility to do over text, especially over the wider internet 
dimitarvp
Yeah, same thinking. If there’s anything I can relegate to the computer to fail early so I can fix it quickly and move on, I’ll do it. I’ll take this to the absolute extremes. (To the point that I worked with
combyandsemgrepseveral times to try and detect anti-patterns in code; hey, if I succeed then maybe that’s one thing I can charge money for consulting, who knows!)Rant blurb: I really feel people often forget “computers must serve us, not us serving them”. (And this is not pointed at the other poster @JohnnyCurran, just a general complaint.)
dimitarvp
Eh, yes and no. If function heads grow that big so as troubleshooting becomes difficult, this outlines two serious problems:
FunctionClauseErrorat this non-early stage of the project still? Those bugs should have been fixed already. They are early-stage “we are still not sure what this external API might return” things. After one month in production these should be gone.So you’re not wrong on the outset but I’d argue that the issues you mention absolutely should be non-issues at this lifecycle stage of the project.
To address your next comment: sure, that’s valid. I suppose for part of the scenarios that technique can help. I still would not though, to me function head pattern matching is an all-or-nothing. When we start mixing both that + matching in body it gets confusing and code-smelly to me. I’d rework it.
JohnnyCurran
Yes, precisely, and I think a good example that may illustrate what I’m trying to say a little better may be –
Let’s consider for a moment that my app is capable of communicating with Google Bard as well as OpenAI,
My LiveView may make a function call like this:
In my context, I unwrap only what’s necessary to determine which function head to take:
MatchErrors now point me directly to the specific function head where the error occurred
adw632
Definitely prefer the function head approach, declarative programming at its finest.
You give me this and I return that, no if’s, cases or maybes.
JohnnyCurran
Elixir will only show the line number of the first defined function head (on a FunctionClauseError). It will also log each function head it attempted to take - if each function head is unwrapping several values that are orthogonal to the flow control, it becomes difficult to tell which one should have been taken.
That leaves the developer in the unfortunate position of figuring out