Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elixir Operator Overloading: Defining an exclusive range using Macros

To understand the Elixir language better, I wanted to try to do operator overloading, by adding an exclusive range operator, .... An example: 1...10 would then create a range from 1 up to but excluding 10 . (e.g. 1...10 == 1..9)

So, I looked up the definition of .., because the functionality of ... would of course be very similar.

Mmy module then became:

defmodule Sequences.Ranges do

  defmacro first ... last do
    case is_float(first) or is_float(last) or
         is_atom(first) or is_atom(last) or
         is_binary(first) or is_binary(last) or
         is_list(first) or is_list(last) do
      true ->
        raise ArgumentError,
          "ranges (first...last) expect both sides to be integers, " <>
          "got: #{Macro.to_string({:"Sequences.Ranges...", [], [first, last]})}"
      false ->
        case __CALLER__.context do
          nil -> quote do: Elixir.Range.new(unquote(first), unquote(last-1))
          _   -> {:%{}, [], [__struct__: Elixir.Range, first: first, last: (last-1)]}
        end
    end
  end

end

However, upon compiling this module, I get the following error:

== Compilation error on file lib/sequences/ranges.ex ==
** (CompileError) lib/sequences/ranges.ex:6: cannot invoke local .../1 inside match
    (stdlib) lists.erl:1353: :lists.mapfoldl/3

What am I doing wrong?

like image 576
Qqwy Avatar asked Mar 19 '16 19:03

Qqwy


People also ask

How will you explain macros in Elixir?

Macros in Elixir are defined via defmacro/2 . For this chapter, we will be using files instead of running code samples in IEx. That's because the code samples will span multiple lines of code and typing them all in IEx can be counter-productive. You should be able to run the code samples by saving them into a macros.

When should I use macros Elixir?

In Elixir, macros are used to define things that would be keywords in other languages: defmodule , def , defp , defmacro , and defmacrop are all macros defined by the standard library in Kernel .

What is use Elixir?

So What Is 'use'? here's a lightweight explanation of 'use' in elixir as I currently understand it. Use is a tool to reuse code just like require, import, and alias. Use simply calls the __using__ macro defined in another module. The __using__ macro allows you to inject code into another module.


1 Answers

There are only a limited number of infix operators that you can define in Elixir:

\\, <-, |, ~>>, <<~, ~>, <~, <~>, <|>, <<<, >>>, |||, &&&, and ^^^

They are predefined in the parser, but not implemented (or at least are not imported by default). This makes them available for custom implementations, but you can't create your own to add to this list unless you modify and recompile Elixir itself.

... is not one of them, so it won't work.

From the comment:

|||, &&&, ^^^, <<<, >>> and ~~~ are not by default imported, but are part of the default Elixir standard library's Bitwise module.

See http://www.rodneyfolz.com/custom-infix-functions-in-elixir/ for more details.

like image 151
CoderDennis Avatar answered Oct 19 '22 08:10

CoderDennis