Kaveh Shahbazian
Kaveh Shahbazian

Reputation: 13521

Pattern Matching Against Records as Tuples in Erlang (Elixir)

Is it a bad practice to pattern match against record as tuples in Erlang (or Elixir)?

Sample code: Assume we have defined this module:

defmodule Ween do
  defrecord TimeSpot, at: nil, tag: nil

  def proper?({ _, _, "home"} = v),   do: { true,   "succeeded with:  #{inspect v}"     }
  def proper?(other),                 do: { false,  "failed with:     #{inspect other}" }

  def sample, do: TimeSpot.new(tag: "home")
end

If we define a test as follow:

defmodule WeenTest do
  use ExUnit.Case
  require Ween

  test "records are tuples" do
    case Ween.proper?(Ween.sample) do 
      { true, v }       ->  IO.puts v
                            assert(true)
      { false, v }      ->  IO.puts v
                            assert(false)
    end
  end
end

It will succeed.

Edit 1: @parroty The reason that here pattern matching against tuples tested is to simulate some "sort of" duck typing for records; the ultimate thing I wished for, should look like this:

defmodule Ween do
  defrecord TimeSpot, at: nil, tag: nil

  def proper?([tag: "home"] = v),          do: { true,   "succeeded with:  #{inspect v}"     }
  def proper?([tag: "1234"] = v),          do: { true,   "succeeded with:  #{inspect v}"     }
  def proper?(other),                      do: { false,  "failed with:     #{inspect other}" }

  def sample, do: TimeSpot.new(tag: "home")
end

So every record with a 'tag' field baring a "home" value would match the first clause. Of-course it seems there would be some performance penalties there.

Upvotes: 3

Views: 2457

Answers (3)

The Wildgoose
The Wildgoose

Reputation: 11

Just for completeness (as this question is still very high on the Elixir tagged questions list): as of Elixir 0.13, records are deprecated (other than for interacting with Erlang code) and the question is now best implemented using Structs. These also conveniently give you the polymorphism that you desire (Structs are a form of Map)

http://elixir-lang.org/getting_started/15.html

Upvotes: 1

parroty
parroty

Reputation: 1375

I think the record can be directly used for pattern matching (this would be better than using tuple structure).

defmodule Ween do
  defrecord TimeSpot, at: nil, tag: nil

  def proper?(TimeSpot[tag: "home"] = v),  do: { true,   "succeeded with:  #{inspect v}"     }
  def proper?(other),                      do: { false,  "failed with:     #{inspect other}" }

  def sample, do: TimeSpot.new(tag: "home")
end

Upvotes: 4

Don Branson
Don Branson

Reputation: 13707

Cesarini and Thompson say in their book Erlang Programming to never rely on the fact that records are implemented as tuples, since that implementation could change. See the accepted answer to this question.

Upvotes: 4

Related Questions