Huolong

Huolong

Type-level guards on top-level body-less function head

The top-level body-less function clause in a multi-head function
is currently used for defining default argument values,
and argument names for doc.

There are two kinds of guards:

  • Type-level guards that enforce the argument types for all function clauses.
  • Guard-matching clauses that select amongst function bodies.

It is tiresome and error-prone to duplicate type-level guards in every specific function head. It also clutters the guards, and makes it difficult to distinguish the type-level enforcement and the selective guards.

I propose the language is changed to allow guards on the body-less top-level function head. These would be the type-level guards to be applied as a precondition before any other function clause is matched, or perhaps ANDed with every other function clause to let the Erlang guard/pattern compiler factor out the common guards to the front of the match execution.

I have had this desire for some time, but what triggered this post and suggestion is seeing this in the Stream implementation:

  def take(enum, count) when is_integer(count) do
    take_after_guards(enum, count)
  end

  defp take_after_guards(_enum, 0), do: %Stream{enum: []}

  defp take_after_guards([], _count), do: %Stream{enum: []}

  defp take_after_guards(enum, count) when count > 0 do
    lazy(enum, count, fn f1 -> R.take(f1) end)
  end

  defp take_after_guards(enum, count) when count < 0 do
    &Enumerable.reduce(Enum.take(enum, count), &1, &2)
  end

Obviously someone else has had the same thought.

With my suggestion, the above code would become:

  def take(enum, count) when is_integer(count) 

  def take(_enum, 0), do: %Stream{enum: []}

  def take([], _count), do: %Stream{enum: []}

  def take(enum, count) when count > 0 do
    lazy(enum, count, fn f1 -> R.take(f1) end)
  end

  def take(enum, count) when count < 0 do
    &Enumerable.reduce(Enum.take(enum, count), &1, &2)
  end

- Fire Dragon

Most Liked

eksperimental

eksperimental

The “convention” that we have been using in Elixir core is to suffix the function names with _guarded Code search results · GitHub.

I worked years ago on a project to implement something like this,
This one was called defensure (and its counterpart deffail) which was a macro which created a function definition that will generate a negation of your clauses,
in your example it will generate

def take(enum, count) when not( is_integer(count) ),
  do: raise(FunctionClauseFailError)

If your proposal is accepted, it think it should introduce a new syntax for this feature and not extend on top of def/defp

dimitarvp

dimitarvp

Very nice pointer about the _guarded suffix! I’ll follow that from now on. :041:

Where Next?

Popular in Discussions Top

jswny
I would like to better understand what the advantages/disadvantages of umbrella applications are compared to structuring your app as as s...
New
Donovan
Hello everyone, I’m so glad to have discovered this awesome community. Thanks for creating it! This is my second post, and apologies for...
New
mikl
I wanted to capitalize a string, and tried using String.capitalize(). That generally works well, until you try to capitalize a word like...
New
Fl4m3Ph03n1x
Background This question comes mainly from my ignorance. Today is Black Friday, one of my favorite days of the year to buy books. One boo...
New
IVR
Hi all, I’ve seen a number of related threads in the past, but I’d still be very curious to hear an up-to-date opinion on this topic. I...
New
Qqwy
I would like to spark a discussion about the static access operator: .. For whom does not know: it is used in Elixir to access fields of...
New
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New
scouten
I’m looking for a host for the server part of a small (personal) side project that I’m working on. It’s currently written in Node.js and ...
New
Owens
Hello all, I am developing a new mobile app with Flutter frontend and Phoenix backend. The mobile app has real-time task management and c...
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New

Other popular topics Top

sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
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
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New

We're in Beta

About us Mission Statement