2019 BEAM wish list

Should the ♮ char be for sets, it’d look like:

  def my_fun(♮{:a, :b} = my_set) do
    "#{my_set} contains :a and :b"
  end

  def my_fun(♮{:c, :b} = my_set) do
    "#{my_set} contains :b and :c"
  end

  def my_fun(my_set) do
    "#{my_set} does not contain :a and :b or :b and :c"
  end

Today I often end up writing something like:

  def my_fun(my_set) do
    if :a in my_set and :b in my_set do
      "#{my_set} contains :a and :b"
    else
      if :c in my_set and :b in my_set do
        "#{my_set} contains :b and :c"
      else
        "#{my_set} does not contain :a and :b or :b and :c"
      end
    end
  end

But frankly it’s just an idea and I have no idea what the semantics would be exactly and if it makes sense at all. Also, it could be implemented in a lib thanks to macros using maps with nil values.

1 Like

Creating mobile apps with Elixir/Scenic. Maybe with a nerves target of Android/ios.

You can always create your own sigil that will provide you similar functionality, my quick attempt at writing something like that is:

defmodule SetSigil do
  defmacro sigil_g({:'<<>>', _, [data]}, opts) do
    {entries, _} = Code.eval_string("[#{data}]")

    set = MapSet.new(entries)

    quote do: unquote(Macro.escape(set))
  end
end

defmodule Foo do
  import SetSigil

  def match(~g(:a, :b, :c)), do: true
  def match(_), do: false

  def main do
    IO.inspect match(MapSet.new([:a, :b, :c, :d])) #=> true
    IO.inspect match(MapSet.new([:a, :b, :c])) #=> true
    IO.inspect match(MapSet.new([:a, :b, :d])) #=> false
    IO.inspect match(MapSet.new()) #=> false
  end
end

Foo.main

It has few downsides (it do not provide way to use local variables), but works.

EDIT

Your sample code could be written as:

def my_fun(my_set) do
  current = MapSet.new([:a, :b, :c])
  intersection = MapSet.intersection(my_set, current) |> MapSet.to_list()

  # Here you work against plain old list of common values
end

Updated version of the sigil module (which now allows using variables in remote calls):

defmodule SetSigil do
  defmacro sigil_g({:'<<>>', _, [data]}, _opts) do
    {:ok, entries} = Code.string_to_quoted("[#{data}]")

    case __CALLER__.context do
      nil ->
        quote do: MapSet.new(unquote(entries))
      _ ->
        {set, _} = Code.eval_quoted(quote do: MapSet.new(unquote(entries)))

        quote do: unquote(Macro.escape(set))
    end
  end
end

defmodule Foo do
  import SetSigil

  def match(set) when set == ~g(:a, :b, :c), do: :exact
  def match(~g(:a, :b, :c)), do: :match
  def match(_), do: :none

  def main do
    foo = 666

    IO.inspect ~g(foo)
    IO.inspect match(MapSet.new([:a, :b, :c, :d]))
    IO.inspect match(MapSet.new([:a, :b, :c]))
    IO.inspect match(MapSet.new([:a, :b, :d]))
    IO.inspect match(MapSet.new())
  end
end

Foo.main
3 Likes

:raised_hands:

I’m hoping that one or more of Gleam, Alpaca, Purerl, and Gradualizer get sufficient momentum to start to be usable in the real world :slight_smile:

5 Likes