Crowdhailer

Crowdhailer

Creator of Raxx

It is rare to use direct calls to send in elixir. The call is normally wrapped in a function which is responsible for sending the correct message. The most common example of this has to be GenServer.call. This is seen as good practice as it allows the structure of the message to be hidden. The structure of the message being an implementation detail only.

However when receiving a message or pattern matching the internal details must always be known. At least this is certainly true in erlang but does not need to be true in Elixir because it has macros.

The most simple case I can think of is the convention of using {:ok, value} || {:error, reason}. This is an implementation of how a function can indicate it has succeeded or failed. It would be possible to use another convention for example %Try.Success{value: value} || %Try.Failure{reason: reason}. To hide which implementation is being used macros can be employed. E.g in a case statement. (The same is true in a receive block).

For example.

case my_func() do
  {:ok, value} ->
    # continue
  {:error, reason} ->
    # report error
end

can be replaced with what I call “semantic pattern matching”

case my_func() do
  success(value) ->
    # continue
  failure(reason) ->
    # report error
end

An implementation of the success and fail macros is available in my OK project.

I will admit that the extra value in this case might not be very high. The example of :ok/:error tuples is both simple and common knowledge. However I think it could be very useful in a few cases, for example.

  • When a process could receive messages from two different libraries. e.g. a Gen server that is running taskes. It might receive a call message or a message notifying of a completed task.
  • A finite statemachine that is receiving commands to change state.

Showing Posts 1 to 10

sztosz

sztosz

I’m not sure I follow. Is there more to this than changing {:ok, value} -> into success(value) -> and {:error, reason} -> to failure(reason) -> ?

I mean, does the success and failure functions/macros do anything more than pattern match inside them to value and reason? What If i want to pattern match to simple :error or {:error, reason, metadata} or something similar?

To be perfectly honest I don’t see any value added here :frowning: To me it neither looks more readable, even in example above :ok and :error have distinct color, so it’s easier to catch them in the code, nor give any usable abstraction or “shortcut” to make development cycle shorter.

But as I stated at the beginning I might simply not understand the purpose fully ¯\_(ツ)_/¯

minhajuddin

minhajuddin

Pattern matching is one of the best superpowers that erlang/elixir have. We should not try to decorate/hide pattern matching with other stuff by adding more magic. I agree that having more expressive atoms may be helpful, but this may not be the best way to go about it, See Usage of {:ok, result} / :error vs {:some, result} / :none . To me it seems like we are adding more noise without giving the user much in return.

josevalim

josevalim

Creator of Elixir

For what is worth, this is a question I frequently ask myself: if it is worth adding abstractions on top of pattern matching and provide conveniences such as defpattern and/or defguard? It is one of those things I am somewhat glad the Erlang VM restrict us from generalizing because we would probably have done so some time ago and the solution may not have been ideal.

Maybe one day we will add something that resembles discriminated unions and named patterns, which would give the features you described above, but right now there are still many questions around on how to generalize such patterns while providing good performance and sane semantics. The current mechanism, although it may be repetitive some times, it is simple, explicit and straight-forward. See the expat thread for a similar discussion.

11
Post #3
Crowdhailer

Crowdhailer OP

Creator of Raxx

Thanks for the comment and the expat thread looks interesting.

Well it’s an excellent situation that the macro system allows experiments with stuff like this. I might try out what it looks like in some of the other examples I mentioned and share the results later on.

Qqwy

Qqwy

TypeCheck Core Team

I believe that if your patterns become too complex in a single function, then that might be a very clear indicator that that function could be split in smaller parts.

I do like pattern-matching extensively to ensure that people know it right away when they put garbage in my libraries’ functions. Sometimes these matches become relatively long. I have been tempted to fiddle with pattern-providing macros before, but have not gone through with it until now because I also believed that this would make it harder to read what was going on. I think there are some use cases where you frequently want to match a struct that is in a certain state.

I agree with @josevalim and @crowdhailer: This is not something Elixir itself should provide, but it is great that we can, if it turns out to be useful for the project at hand, write macros that do this stuff.

josevalim

josevalim

Creator of Elixir

@Qqwy yup, that is a good summary of my thoughts on the topic as well.

NobbZ

NobbZ

I do not think that there is value in hiding :ok and :error tuples from the user.

But a feature I’d really like where something that makes it possible to match on various kinds of data structures as if they were something else. This would make some nice things possible.

Imagine a module that implements a lengthaware list. roughly like this:

defmodule LengthAwareList do
  defstruct length: 0, value: nil, next: nil
end

If one wants to pattern match on this, he needs to know the exact structure of the struct, but this should be abstracted away by function calls according to current level of research in CS.

Therefore it would be nice to be able to define some kind of “view” to this datastructure, which makes it appear as a regular list in a patternmatch.

But I do see though, that such a feature is far out of scope what a macro or even elixir lang could do. This were a feature that needs to be available from within BEAM.

Also I think, that BEAMs strictness is also in the way here, since we would convert the complete LAL to a default List all the time, even when only matching on the first member.

A very similar feature that I describe is known as “pattern view” in the Haskell world and was available as an experimental feature when I looked last time.

Crowdhailer

Crowdhailer OP

Creator of Raxx

I don’t quite understand your example here. Would a length list match like the following be helpful.

case my_list do
  vector(3, content) when is_binary(content) ->
  # equivalent to
  [a, b, c] when is_binary(a) and is_binary(b) and is_binary(c) ->
  # or for a length three list containing anything
  vector(3, _) -> 
end
OvermindDL1

OvermindDL1

Whooo!

Ditto, they are too simple and they are basically a tagged_union/discriminated_union/Variant_type anyway. ^.^

kelvinst

kelvinst

Perfectly describes my opinion too! I would just mention a little bit of the old uncle Ben: “Remember, with great power comes great responsibility”.

This possibility is like a superpower to rewrite the whole language your way if you want, but it is common to create a monster and at that point, the way back is just as painful as to stay with the monster.

Where Next? Top

Trending in Discussions Top

wmnnd
Hey folks, I wanted to share with you a project I’ve been working on for a while: It’s an Open Source (AGPLv3) newsletter tool. Think Ma...
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
alexslade
Fly’s CEO posted this recently - Turn And Face The Strange · The Fly Blog It says that Fly is going all-in on sprites, which is a worry ...
New
sntran
In my third year of college, around 2010, I found Erlang. A few years later, I found Elixir. I liked the ideas at once: many small proces...
New
Ganna
Hi everyone, I have 8 years of production experience with Erlang/OTP and I’m just starting to get to know Elixir. What would you learn f...
New
johnkirkham
A note on form. Joe Armstrong, co-creator of the Erlang programming language, died in April 2019. What follows is a work of narrative non...
New
gtcode
I’ve been tinkering with Lynx (by José) via hold_ledger. I used AI to write the code, a separate specification, the tests, and the Lean p...
New

Other Trending Topics Top

dominicletz
Hey there, I haven’t seen a list of useful Elixir specific skills for the popular AI tools yet so I’m starting one here with my first. ...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
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
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New
OndrejValenta
(I just needed to vent somewhere and LinkedIn is full of hope, or hype, I’m not sure which exactly) AI dream has many faces, but general...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews