daviaws

daviaws

I’m writing a module to test ets match.
It would to store client consume by month/year.

I had try to follow match spec… I even tried to do automagic translate of elixir functions with GitHub - ericmj/ex2ms: :ets.fun2ms for Elixir, translate functions to match specifications · GitHub

nonetheless I always end up with an empty list []

Please… someone help me with list_period method…

defmodule ETS.Consume do
  @moduledoc """
  Consume tasks

    r ETS.Consume

    ETS.Consume.scenario()

    table = ETS.Consume.start()
    ETS.Consume.populate(table)
    ETS.Consume.list(table, "12345678901")
    ETS.Consume.list_period(table, "12345678901", 2, 2021, 10, 2021)
  """

  import Ex2ms

  @table :cons
  @opts [:ordered_set, :protected]
  def start do
    :ets.new(@table, @opts)
  end

  def insert(ref, cpf_cnpj, mes, ano, consumo) do
    key = {cpf_cnpj, mes, ano}

    :ets.insert(ref, {key, consumo})
  end

  def list(table, cpf_cnpj) do
    :ets.match(table, {{cpf_cnpj, :"$1", :"$2"}, :"$3"})
  end

  def list_period(table, cpf_cnpj, mes_inicio, ano_inicio, mes_fim, ano_fim) do
    pattern = [{{{:"$1", :"$2", :"$3"}, :"$4"}, [{:<, :"$2", 2}], [true]}]

    :ets.match(table, pattern)
  end

  def populate(table) do
    insert(table,  "12345678901", 1, 2021, 100)
    insert(table, "12345678901", 2, 2021, 200)
    insert(table, "12345678901", 3, 2021, 300)
    insert(table, "12345678901", 4, 2021, 200)
    insert(table, "12345678901", 5, 2021, 300)
    insert(table, "12345678901", 6, 2021, 350)
    insert(table, "12345678901", 7, 2021, 200)
    insert(table, "12345678901", 8, 2021, 100)
    insert(table, "12345678901", 9, 2021, 500)
    insert(table, "12345678901", 10, 2021, 300)
    insert(table, "12345678901", 11, 2021, 200)
    insert(table, "12345678901", 12, 2021, 310)
    insert(table, "12345678902", 1, 2021, 310)
  end

  def scenario do
    table = ETS.Consume.start()
    ETS.Consume.populate(table)
    # ETS.Consume.list(table, "12345678901")
    ETS.Consume.list_period(table, "12345678901", 2, 2021, 10, 2021)
  end

  def test() do
    fun do {{ cpf_cnpj, mes, ano }, consumo} = arg when mes < 2 -> true end
  end
end

Showing Posts 1 to 10

daviaws

daviaws OP

My workaround will be match by unique key and manually filter…

But this is clearly naive.

daviaws

daviaws OP

:ets.fun2ms(fn {{ cpf_cnpj, mes, ano }, consumo} when mes < 2 -> ano end)

returns

[{{{:"$1", :"$2", :"$3"}, :"$4"}, [{:<, :"$2", 2}], [:"$3"]}]

even this returns an empty list. This is annoying me… if only there is something I can do to know whats wrong, but this is it, even the official mechanisms are giving unexpected results.

daviaws

daviaws OP

Some gentle and helpful soul, please enlighten me?

My next steps would be:

  1. validate erlang itself working.
  2. check elixir and erlang integration spot.
daviaws

daviaws OP

erl

1> T = ets:new(t,[ordered_set]).
#Ref<0.804086672.212992002.220352>
2> ets:insert(T,  {{"12345678901", 1, 2021}, 100}).
true
3> ets:insert(T, {{"12345678901", 2, 2021}, 200}).
true
4> ets:insert(T, {{"12345678901", 3, 2021}, 300}).
true
5> ets:insert(T, {{"12345678901", 4, 2021}, 200}).
true
6> ets:insert(T, {{"12345678901", 5, 2021}, 300}).
true
7> ets:insert(T, {{"12345678901", 6, 2021}, 350}).
true
8> ets:insert(T, {{"12345678901", 7, 2021}, 200}).
true
9> ets:insert(T, {{"12345678901", 8, 2021}, 100}).
true
10> ets:insert(T, {{"12345678901", 9, 2021}, 500}).
true
11> ets:insert(T, {{"12345678901", 10, 2021}, 300}).
true
12> ets:insert(T, {{"12345678901", 11, 2021}, 200}).
true
13> ets:insert(T, {{"12345678901", 12, 2021}, 310}).
true
14> ets:insert(T, {{"12345678902", 1, 2021}, 310}).
true
15> ets:tab2list(T).
[{{"12345678901",1,2021},100},
 {{"12345678901",2,2021},200},
 {{"12345678901",3,2021},300},
 {{"12345678901",4,2021},200},
 {{"12345678901",5,2021},300},
 {{"12345678901",6,2021},350},
 {{"12345678901",7,2021},200},
 {{"12345678901",8,2021},100},
 {{"12345678901",9,2021},500},
 {{"12345678901",10,2021},300},
 {{"12345678901",11,2021},200},
 {{"12345678901",12,2021},310},
 {{"12345678902",1,2021},310}]

And so…

17> ets:match(T, [{{{'$1', '$2', '$3'}, '$4'}, [{'<', '$2', 2}], ['$3']}]).
[]
daviaws

daviaws OP

### [ETS] Does :ets.match spec really works?

daviaws

daviaws OP

Following the official docs: Match Specifications in Erlang — OTP 29.0.2 (erts 17.0.2)

1> T = ets:new(t,[ordered_set]).
#Ref<0.1704239209.3973709829.71159>
2> ets:insert(T, {strider, 1, 2021}).                                        
true
3> ets:match(T, [{{strider,'_','_'}, [], ['$_']}]).
[]

:smile: 5 hours of my life… to uncover that I will need to do Enum.filter :eyes:

al2o3cr

al2o3cr

There’s an unfortunate overlap in terminology: :ets.match takes a “match pattern”, not a match specification. The documentation for :ets.select/2 demonstrates this:

ets:match(Table,{'$1','$2','$3'})

# is equivalent to

ets:select(Table,[{{'$1','$2','$3'},[],['$$']}])

Demo:

iex(1)> tab = :ets.new(:foo, [:ordered_set])
#Reference<0.3893230368.2635726851.91982>

iex(3)> :ets.insert(tab, {{"a", 1, "b"}, "c"})
true

iex(4)> :ets.insert(tab, {{"d", 2, "e"}, "f"})
true

iex(6)> :ets.select(tab, [{{{:"$1", :"$2", :"$3"}, :"$4"}, [{:<, :"$2", 2}], [:"$_"]}])
[{{"a", 1, "b"}, "c"}]
daviaws

daviaws OP

Thank you so much!!! I’ve been researching the topic for a while.

Thank you thank you thank you!!

It worked :smiley:
image

ityonemo

ityonemo

(Self promotion) you might find this library to be helpful for you to go either way:

daviaws

daviaws OP

Hello @ityonemo

whats the advantage over using :ets.fun2ms/1 ?

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
jonnycharles
I’m in search of an Elixir library that offers PDF generation capabilities similar to Ruby’s Prawn. While there have been discussions abo...
New
spammy
I’m looking to build a personal workflow to quickly deploy web applications written in elixir/phoenix, for local consumption (ie not on t...
New
dli
Before I dive in myself, did anyone successfully sprinkle Hologram into their existing LiveView app? Looking for hints regarding: Addi...
New
roeland
Kia ora, We have been using elixir-google-api to connect to Google Drive. However, with the updates to Tesla due to CVEs this is now bro...
New
bottlenecked
Hi all, I wanted to ask how the community is dealing with post-release steps. Today we have Ecto migrations, which make sure that the db...
New
rahultumpala
Hello, I have an Elixir backend that implements a custom protocol over TCP. I want to load test the backend and assess the performance o...
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
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews