nikolis

nikolis

Fair warning I come from an OOP backround so I might be missing something very obvious here.

Hierarchical Selection of value

Lately I have been trying to go over my elixir project and try to identify potential patterns in the code. One such pattern that I “identified” from my own code when I was working with developing custom components like for example a LiveSearchSelect component etc is the need to get a value through a hierarchical structure like for example get the field value from

  1. The form params (for example to get the values of the users latest changes)
    but if this is nil
  2. The changeset(For example if the form param are empty due to an update triggered through the changes happened from a javascript trigger interceptor which also triggers re render of the custom component)
    but if this is also nil
  3. Maybe some case that exist to save user progress
    but if this is also nil
    “empty string”

So I found this as a let’s say re occurring problem and I came up with a name in order to standardize a solution on this kind of problem for the context of my project at least.

The solution I found to be the most elegant and easy to maintain is the following

{first-degree, second-degee, thrid-degree}  = {get_val, .., ..}
case tuple do 
    {nil, nil, nil } ->
      whatever 
    {nil, nil, third-degree } ->
      third-degree
    {nil, second-degree, _ } ->
      second-degree
    {first-degree, _, _} ->
      third-degree
 end

Do you relate/have any to share?

So I wanted to share this mainly to ask whether other developers can relate ?? and if you have also “project level” patterns with standardized solutions on common problems of either your domain or in general when working with Elixir PhoenixLiveView and relevant technologies.

Showing Posts 1 to 10

cmo

cmo

I would use with or || to avoid calling each getter. You might only need to call the first one.

nikolis

nikolis OP

The reason for the case do structure was that no matter the amount of layers there is not going to be any nesting, which would lead to code that is easy to test and maintain in general. Although I hear the argument about not needing to get all the values, in most cases this is very cheap operation. So in order for the with to make sense, it would need to not make any sacrifices in the “complexity/nesting” side of things, so how would you approach the same problem if you used with instead ?

sodapopcan

sodapopcan

with nil <- get_first_val(),
     nil <- get_second_val() do
  get_third_val()
end

or just:

get_first_val() || get_second_val() || get_third_val()

EDIT: I missed the whatever so if that is important, your case would use with like so:

with nil <- get_third_val(),
     nil <- get_second_val(),
     val <- get_first_val() do
  # do whatever with val
end
nikolis

nikolis OP

About the first part I understand that you still need to define other outcomes for example what happens if you end up getting a result from the “get_second_val” then you still need to match that in the else statement making the hierarchy of the code less apparent (the way I see it) and when it comes to the second approach it’s for sure the most elegant but for me it did not work on the debug phase.

But in general the point of the thread was not to argue about the particular peace of code but rather open a discussion of less common design patterns that might be somewhat domain specific on the context of Phoenix LiveView does this make sense ?

garrison

garrison

This is pretty much the canonical with use-case as mentioned above, but for times when you already have all of the values a cond can also be used for nil-handling.

cond do
  first_value -> whatever(first_value)
  second_value -> second_value
  true -> default
end

Which is equivalent to this (but easier to read if there are many cases):

(first_value && whatever(first_value)) || second_value || default
cevado

cevado

i’d use a cond in this context, something like:

cond do
  first = get_first() when not is_nil(first) -> ...
  second = get_second() when not is_nil(second) -> ...
  third = get_third() when not is_nil(third) -> ...
  true -> whatever
end

if you see not is_nil(value) getting repeated a lot, i’d define a guard in this module:

defguard not_nil(value) when not is_nil(value)
sodapopcan

sodapopcan

Certainly wasn’t trying to argue.

Fully agreed on cond. It seems many people forget about it and I actually know people who actively avoid it (which I don’t fully understand). It’s probably the least used construct but really useful when it is :slight_smile:

Otherwise, for specific LiveView stuff, I would need to see more code as there may be cleaner ways of structuring it. For example (and this keeps coming up lately), I very very rarely look at params—I would pass them right to the changeset then check if changes is empty. Otherwise, if a whole key is missing, I would maybe handle these in different handle_event matches. But again, very hard to say without seeing more explicit code.

PS lol at your new avatar, @cevado :sweat_smile:
EDIT: It may have been a glitch but your avatar has changed again.

D4no0

D4no0

I personally like cond too instead of the generic nested case or if/else, but I am not a big fan of assignments in either cond/if, it’s a little bit too much magic, it’s completely confusing for folk that didn’t write elixir and even for newcomers.

garrison

garrison

The cond will naturally guard against nil (it is falsey). And I don’t think you can use guards in a cond anyway, right?

But I agree with the spirit of your post, and actually I think this is probably better than with:

cond do
  first = get_first() -> first
  second = get_second() -> second
  true -> default
end

But this is all only for nil-handling. If we were dealing with :ok/:error tuples it would be a different story.

sodapopcan

sodapopcan

I do this constantly. I feel understanding that everything is an expression is required knowledge if you’re going to be writing Elixir. A bit off topic, though.

Where Next? Top

Trending in Discussions Top

cblavier
Hey there, It’s been more than a year since we started using LiveView as our main UI library and building a whole library of UI componen...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
budgie
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
achempion
I’ve been using Emacs as my main code editor for more than a two years. It’s a custom build version although I’ve tried doom emacs and sp...
New
axelson
Hi there! :wave: @frigidcode and I (but mostly him) have been running an Elixir Book club, we’re almost done with Designing Elixir Syste...
New
budgie
I love Elixir. It’s one of 2 programming languages I’ve ever fallen in love with. But I don’t use it anymore. Serverless was the promis...
New

Other Trending Topics Top

GenericJam
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
JesseHerrick
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
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
georgeguimaraes
Just published claude-code-elixir, a plugin marketplace for Claude Code with Elixir support. These are the plugins I’ve been using for my...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews