spencer.christensen

spencer.christensen

Should strings be wrapped in a function in functional programming?

I’m going through Tate and DeBenedetto’s Programming Phoenix LiveView and observed the code below.

  defp assign_chart_svg(%{assigns: %{chart: chart}} = socket) do
    socket
    |> assign(:chart_svg, render_bar_chart(chart, title(), subtitle(), x_axis(), y_axis()))
  end

  defp title do
    "Product Ratings"
  end

  defp subtitle do
    "Average star ratings per product"
  end

  defp x_axis do
    "products"
  end

  defp y_axis do
    "stars"
  end

As somebody new to functional programming, I’m wondering whether this granular-level of function definitions is typical? I can see some options:

  • it is idiomatic and a best practice to wrap strings in a function.
  • it is only a best practice to wrap a string in a function when the function name can clarify the purpose of the string (“stars” is not as descriptive as y_axis)
  • it is unusual and is likely being done to account for some sort of future abstraction that relies on a callback of said functions

I’m not arguing for or against anything, just curious for best-practices and idiomatic Elixir use of string binaries. Thanks!

Most Liked

christhekeele

christhekeele

This is correct—it is a conceit they are using to keep the examples focused to the “lesson” at hand: learning Liveview; and to leave “room to grow” the examples with later functionality.

@mindok’s posts concerning module attributes are the idiomatic approach to this! But you can see why introducing those patterns don’t serve what is being taught: instructive writing can be weird like that sometimes.

mindok

mindok

Probably a more common alternative in Elixir would be to use module attributes. e.g.:

@title "Product Ratings"
@subtitle "Average star ratings per product"
@x_axis "products"
@y_axis "stars"

  defp assign_chart_svg(%{assigns: %{chart: chart}} = socket) do
    socket
    |> assign(:chart_svg, render_bar_chart(chart, @title, @subtitle, @x_axis, @y_axis))
  end
sodapopcan

sodapopcan

Ya, what @mindok said. I have have barely read any of that book so maybe there are going somewhere with it and will flesh it out later? Wrapping strings in functions as a general rule certainly isn’t a “thing” though. I’ve never done it and this is the first time I’ve seen code that does it (I’ve been doing Elixir for around 5 years).

From what I have read of the book, though, they do extract far more than I personally care to. There are lots of small single-user private functions that don’t really read any better than the bare code in my view. I’m not implying the book is bad by any means (how could I know? …and all of Sophie’s stuff I have read and watched is amazing) and while idiomatic Elixir is certainly a thing, it’s not super obsessive and people have varying styles.

EDIT: One reason I can think of to use functions is that heex overloads @ to access assigns. So if you have

@title "Product Ratings"

def assign_thing(socket) do
  assign(socket, :title, @title)
end

def render(assigns) do
  ~H"""
  <%= @title %>
  """
end

That reads super confusingly because the @title in the render function is referring to :title in the socket, not the module attribute @title.

That’s total guess, though.

mindok

mindok

…However, module attributes are private to a module, so to expose them to other modules you would need to use a public function, e.g.

@title "Product Ratings"
@subtitle "Average star ratings per product"
@x_axis "products"
@y_axis "stars"

  defp assign_chart_svg(%{assigns: %{chart: chart}} = socket) do
    socket
    |> assign(:chart_svg, render_bar_chart(chart, @title, @subtitle, @x_axis, @y_axis))
  end

  def the_same_title_we_use_everywhere(), do: @title # or "Product Ratings"
al2o3cr

al2o3cr

render_bar_chart(chart, title(), subtitle(), x_axis(), y_axis()))

IMO this would be clearer as a function that took chart and a keyword list:

render_bar_chart(chart, title: "Product Ratings", subtitle: "...", etc etc)

That avoids the confusion of “what the heck ARE all these unnamed literal positional args” while not spamming private functions.

Where Next?

Popular in Questions Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
tduccuong
Hi, is there any work on GUI with Elixir, that is similar to Electron/Javascript? My idea is to bundle Phoenix and BEAM into a single se...
New
dokuzbir
Hello, I am trying to convert my lists to string without losing brackets.For start i have 3 map. They look like these buyer = %{ id: ...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
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
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
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
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
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

Other popular topics Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
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
Tee
can someone please explain to me how Enum.reduce works with maps
New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 42633 214
New
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
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

We're in Beta

About us Mission Statement