Qqwy

Qqwy

TypeCheck Core Team

In Guard clauses (the when... part after the destructuring section of a pattern match), we’re only allowed to use a very small subset of functions because these are the only ones that the BEAM can optimize and that are known to be pure (side-effect free).

One of the problems of this property of the BEAM, is that it becomes impossible to ‘nest’ guard clauses. In Elixir, we can write macros, allowing us to write short snippets in a guard clause that at compile-time expand to longer pieces of guard-safe functions. But great care needs to be taken to ensure that this macro does not include code that itself tries to pattern match or run guard clauses (or any other type of conditional branching for that matter) because the compiler does not allow this.

In Elixir, we have structs, which are a great type of abstraction to allow many different kinds of user-defined types and work with protocols on them. However, we cannot check properties of a struct inside a guard clause, because it is impossible to destructure a map inside a guard clause (there are no guard-safe functions that can do this).

However, it is possible to bind names to fields of your struct inside the destructuring part of the pattern match, and refer to these names inside the guard clause. But of course, this would mean hard-coding the pattern match every time I want to check if some property of a struct is true.

I think that it is possible to build an abstraction layer that allows this, though. After all, aren’t:

def foo(tuple) when elem(tuple, 0) == :ok do
  # ...
end

and

def foo({42, _} = tuple) do
  # ...
end

the same?

Therefore, why not write something like this:

  def foo(%Box{}) when is_filled(box) do
    # ...
  end

and enhance the Elixir compiler so it will cleverly rewrite it to:

  def foo(%Box{value: tmp0}) when tmp0 != nil do
    # ...
  end

?

I think that by doing this, we would be able to create a lot more possibilities for creating guard-safe macros. I believe that things like the arithmetic operators might finally be able to be made guard-safe as they could dispatch on structs then.

The only downside I can think of, is that it will make compilation a little more difficult.

What do you think? Interesting? Awesome? Horrible?

Showing Posts 1 to 1

OvermindDL1

OvermindDL1

It’d not be ‘that’ hard to do all things considered. The elixir parser would just need to be made aware of matching contexts and call the macros over the whole context instead of just the part it is defined in, I did an experiment with this with my (highly incomplete, do not have time to work on it currently, busy at work) defguard experimentation:

# Defining
defmodule StructEx do
  import Defguard
  defguard is_struct(%{__struct__: struct_name}) when is_atom(struct_name)
  defguard is_struct(%{__struct__: struct_name}, substruct_name) when is_atom(struct_name) and struct_name === substruct_name
  defguard is_exception(%{__struct__: struct_name, __exception__: true}) when is_atom(struct_name)
end


# Using
defmodule Testering do
  use Defguard
  import StructEx

  def blah(any_struct) when is_struct(any_struct), do: 2
  def blah(_), do: 0

  def blorp(exc) when is_exception(exc), do: "exceptioned"
  def blorp(val), do: "No-exception:  #{inspect val}"
end


# Testing
assert Testering.blah(%{__struct__: Blorp}) === 2
assert Testering.blah(42) === 0
assert Testering.blorp(%ArithmeticError{}) === "exceptioned"
assert Testering.blorp(%{__struct__: Blah}) === "No-exception:  %{__struct__: Blah}"

My style here is of course a huge hack, it could be done properly in the compiler itself and more cleanly.

EDIT: Your box example (I think) could be done in my library as-is though (I’ve barely implemented it, just enough for the above examples to work, but this might work):

defmodule Box do
  import Defguard
  defguard is_filled(%Box{value: v}) when v != nil
end

...
  def foo(box) when is_filled(box) do
  end
— All posts loaded —

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 94592 917
New
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
heathen
Quite interesting article Google brought me. Didn’t find any mentions about it here. What do you think in general? Would you use togethe...
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
AstonJ
Since we have deprecated our Erlang sections (as we have dedicated Erlang Forums now) let’s add this thread for those who’d like to post ...
New
Null-logic-0
What IDE or editor are you using for Elixir development? Personally, I use Zed, and I really like it, but sometimes I wish there were a ...
New

Other Trending Topics Top

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
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
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
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
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews