2016-08-17 6 views
0

У меня есть следующие запросы, и, как видно, требуется довольно много копирования/вставки.Очистка повторяющегося кода с помощью макросов?

Есть ли быстрый и элегантный способ решить это с помощью метапрограмм?

def by_day_of_week(query \\ Conversation) do 
    from c in query, 
    select: %{ 
     monday: fragment("count(extract(dow FROM ?) = 0 OR null)", c.inserted_at), 
     tuesday: fragment("count(extract(dow FROM ?) = 1 OR null)", c.inserted_at), 
     wednesday: fragment("count(extract(dow FROM ?) = 2 OR null)", c.inserted_at), 
     thursday: fragment("count(extract(dow FROM ?) = 3 OR null)", c.inserted_at), 
     friday: fragment("count(extract(dow FROM ?) = 4 OR null)", c.inserted_at), 
     saturday: fragment("count(extract(dow FROM ?) = 5 OR null)", c.inserted_at), 
     sunday: fragment("count(extract(dow FROM ?) = 6 OR null)", c.inserted_at), 
    } 
    end 

    def by_time_of_day(query \\ Conversation) do 
    from c in query, 
    select: %{ 
     "00" => fragment("count(extract(h FROM ?) = 0 OR null)", c.inserted_at), 
     "01" => fragment("count(extract(h FROM ?) = 1 OR null)", c.inserted_at), 
     "02" => fragment("count(extract(h FROM ?) = 2 OR null)", c.inserted_at), 
     "03" => fragment("count(extract(h FROM ?) = 3 OR null)", c.inserted_at), 
     "04" => fragment("count(extract(h FROM ?) = 4 OR null)", c.inserted_at), 
     "05" => fragment("count(extract(h FROM ?) = 5 OR null)", c.inserted_at), 
     "06" => fragment("count(extract(h FROM ?) = 6 OR null)", c.inserted_at), 
     "07" => fragment("count(extract(h FROM ?) = 7 OR null)", c.inserted_at), 
     "08" => fragment("count(extract(h FROM ?) = 8 OR null)", c.inserted_at), 
     "09" => fragment("count(extract(h FROM ?) = 9 OR null)", c.inserted_at), 
     "10" => fragment("count(extract(h FROM ?) = 10 OR null)", c.inserted_at), 
     "11" => fragment("count(extract(h FROM ?) = 11 OR null)", c.inserted_at), 
     "12" => fragment("count(extract(h FROM ?) = 12 OR null)", c.inserted_at), 
    } 
    end 
+0

Какие у вас были попытки приблизиться к этой проблеме? Не могли бы вы поделиться ими вместе с проблемами, с которыми вы столкнулись? –

+0

Вы пробовали создать эту карту с другой функцией? Я думаю, вы должны быть способны решить эту проблему без макросов, но если вы настаиваете на их использовании, вы можете это сделать. $ {} - это просто функция. Введите цитату iex do% {whatever} – Haito

+0

Метод «фрагмент» недоступен за пределами 'from' – Tarlen

ответ

0

Если вы действительно хотите сделать это с помощью макросов, вы, вероятно, сможете это сделать.

Running example

defmodule MapUtils do 
defmacro spam(numbers) do 
    quote do 
     Enum.reduce(unquote(numbers), %{}, fn (elem, acc) -> 
     Map.put(acc, elem, elem) 
     end) 
    end 
    end 
end 

Большое спасибо Крису Wende

1

Непроверенные и некрасиво, но я бы сказал что-то вроде:

def days_of_week do 
    days = ~w(monday tuesday wednesday thursday friday saturday sunday)a 

    for {day, index} <- Enum.with_index(days) do 
    {day, quote do fragment("count(extract(dow FROM ?) = ? OR null)", c.inserted_at, unquote(index)) end} 
    end 
end 
defmacro by_day_of_week, 
    do: quote do: %{unquote_splicing(days_of_week)} 

Она производит код:

"%{ 
    monday: fragment(\"count(extract(dow FROM ?) = ? OR null)\", c.inserted_at(), 0), 
    tuesday: fragment(\"count(extract(dow FROM ?) = ? OR null)\", c.inserted_at(), 1), 
    wednesday: fragment(\"count(extract(dow FROM ?) = ? OR null)\", c.inserted_at(), 2), 
    thursday: fragment(\"count(extract(dow FROM ?) = ? OR null)\", c.inserted_at(), 3), 
    friday: fragment(\"count(extract(dow FROM ?) = ? OR null)\", c.inserted_at(), 4), 
    saturday: fragment(\"count(extract(dow FROM ?) = ? OR null)\", c.inserted_at(), 5), 
    sunday: fragment(\"count(extract(dow FROM ?) = ? OR null)\", c.inserted_at(), 6) 
}" 

И соответственно со вторым.