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

AstonJ
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
2977 92995 915
New
caslu
I want to open this thread for you all to discuss and help those who really like Ash but are still hesitant to use it in a real project. ...
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
GES233
I’m posting this in response to Jose’s recent tweet (Cr. link) : People are sleeping on Elixir for a coding harness: Hot-code swappi...
New
_mfierro
Hello, I wrote Stop My Hand, a Scattergories-like web application using Phoenix/LiveView as my learning project for Elixir (after readin...
New
marciol
It would be helpful to have a list of companies worldwide that hire engineers without prior experience in Elixir. Often, it can be quite ...
New
durvia
Anyone running long-lived stateful processes on BEAM? We’re building an AI agent runtime and would love to compare notes. We’re a small ...
New

Other Trending Topics Top

garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
wintermeyer
There are three potential reasons for members of this forum to have a look at https://vutuv.de You are tired or annoyed of LinkedIn. Yo...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews