Size: a a a

2020 September 02

LL

Lama Lover in pro.elixir
Sergei Maximov
А зачем самому в коде её делать? Пусть редактор и форматтер делают.
Это как-то странно звучит...
Ну у меня есть автотабуляция в редакторе, но я её прямо в редакторе вызываю
источник

В

Владислав in pro.elixir
Lama Lover
Суть в том что аттрибуты подставляются до __before_compile__. Можно даже сказать что он подставляется сразу во время его появления в AST (только если кусок кода не в quote)

Обычно аттрибуты не используют для подставления каких-то значений в функцию в __before_compile__, а их используют для аггрегации каких-то значений во время компиляции модуля, для локального стейта компилятора, чтобы не спавнить какие-то агенты и всё такое
Интересно. Просто я привык использовать аттрибуты именно в качестве констант внутри модуля. И потребности в том, чтобы их изменять до компиляции, до текущего момента не было.
источник

AB

Alex Bubnov in pro.elixir
Владислав
и вот так
defmodule Foo do
@before_compile Baz.FooManager
@some_bar [10, 11]
def call_some_bar, do: @some_bar
end
defmodule Baz.Foomanager do
defmacro __before_compile___(env) do
value = Module.get_attribute(env.module, :some_bar)
Module.delete_attribute(env.module, :some_bar)
Module.register_attribute(env.module, :some_bar, accumulate: true)
Module.put_attribute(env.module, :some_bar, [9 | value])
end
end
iex> Foo.call_some_bar
#=> [10, 11]
А зачем ты удаляешь атрибут?
источник

SM

Sergei Maximov in pro.elixir
Lama Lover
Это как-то странно звучит...
Ну у меня есть автотабуляция в редакторе, но я её прямо в редакторе вызываю
Ну обычно по нажатию enter редактор сам выбирает нужное выравнивание, если где-то выровнял не так — то всё равно после сохранения автоматом запускается форматтер.
источник

В

Владислав in pro.elixir
Alex Bubnov
А зачем ты удаляешь атрибут?
Эксперимент. Думал, что register_attribute не отработает корректно, если не удалить старый аттрибут
источник

В

Владислав in pro.elixir
Но у меня и так и так не получилось сделать)
источник

МБ

Максим Барулин... in pro.elixir
А в общем рейтинге 80
источник

B

Bogdan in pro.elixir
Vyacheslav Konovalov
comprehensions vs Enum.map
как выбрать? или разницы нет?
Есть разница, в comprehansion есть фильтрация редукция , into.

for x <- 0..10, y <- 5..20, x > 2 and y < 15, 
do: {x, y + x}, into: %{}
источник

LL

Lama Lover in pro.elixir
Использовать аттрибуты как константы можно только в каком-нибудь MVC или когда эти константы зависят от самого модуля (например @enforce_keys) или ещё какой-нибудь список полей/определённых значений

Если использовать аттрибуты как какие-то константные настройки (типа размер пулла, таймаут и прочее) можно легко попасть в просак с их изменением при компиляции/рантайме. Поэтому для таких конфигураций лучше использовать Application Env или persistent_term или FastGlobal или ещё что...
источник

В

Владислав in pro.elixir
Сейчас вот сделал так
defmodule Foo do
 @before_compile Baz.FooManager
 @some_bar [10, 11]
 def call_some_bar, do: f_some_bar()
end

defmodule Baz.Foomanager do
 defmacro __before_compile___(env) do
   value = Module.get_attribute(env.module, :some_bar)
   quote do
     def f_some_bar, do: [9 | value]
   end
 end
end

iex> Foo.call_some_bar
#=> [9, 10, 11]
источник

LL

Lama Lover in pro.elixir
Для какой-то хитрой кодогенерации использовать ти константы немного странно
источник

VK

Vyacheslav Konovalov in pro.elixir
Bogdan
Есть разница, в comprehansion есть фильтрация редукция , into.

for x <- 0..10, y <- 5..20, x > 2 and y < 15, 
do: {x, y + x}, into: %{}
я вот забыл совсем, что for это как фильтр, и если паттерн не матчится, то элемент пропускается
источник

LL

Lama Lover in pro.elixir
Владислав
Сейчас вот сделал так
defmodule Foo do
 @before_compile Baz.FooManager
 @some_bar [10, 11]
 def call_some_bar, do: f_some_bar()
end

defmodule Baz.Foomanager do
 defmacro __before_compile___(env) do
   value = Module.get_attribute(env.module, :some_bar)
   quote do
     def f_some_bar, do: [9 | value]
   end
 end
end

iex> Foo.call_some_bar
#=> [9, 10, 11]
А зачем такой monkey patching вообще нужен? Какая изначальная проблема?
источник

AB

Alex Bubnov in pro.elixir
А что вообще делают в before_compile? И что там вообще можно сделать?..
источник

LL

Lama Lover in pro.elixir
Если нужно просто генерить одинаковую функцию в нескольких модулях которая возвращает определённое значение, то лучше использовать __using__ с defoverridable
источник

LL

Lama Lover in pro.elixir
Alex Bubnov
А что вообще делают в before_compile? И что там вообще можно сделать?..
Ну есть у тебя в модуле функции какие-то. Ты хочешь на их основе ещё какую-то функцию сгенерить.

Пример: в модуле лежат функции-хэндлеры для определённых роутов и хочется сделать общий эндпоинт, который будет вызывать нужную функцию по константому паттерн-матчингу
источник

В

Владислав in pro.elixir
Lama Lover
Использовать аттрибуты как константы можно только в каком-нибудь MVC или когда эти константы зависят от самого модуля (например @enforce_keys) или ещё какой-нибудь список полей/определённых значений

Если использовать аттрибуты как какие-то константные настройки (типа размер пулла, таймаут и прочее) можно легко попасть в просак с их изменением при компиляции/рантайме. Поэтому для таких конфигураций лучше использовать Application Env или persistent_term или FastGlobal или ещё что...
Согласен. До сегодняшнего дня аттрибуты такими и были. Т.е. ты знаешь, что в рантайме ты их не поменяешь, поэтому это константы и с этим ничего не поделаешь.

Однако, в текущем проекте написано большое кол-во кода, где юзается аттрибут как константа. Теперь понадобилось чтобы данный атрибут изменялся в зависимости от наличия тех или иных модулей.
источник

В

Владислав in pro.elixir
И вот начались эксперименты
источник

AB

Alex Bubnov in pro.elixir
Before_compile возвращает дополнительный ast, не рерайт старого, да?
источник

LL

Lama Lover in pro.elixir
Владислав
Согласен. До сегодняшнего дня аттрибуты такими и были. Т.е. ты знаешь, что в рантайме ты их не поменяешь, поэтому это константы и с этим ничего не поделаешь.

Однако, в текущем проекте написано большое кол-во кода, где юзается аттрибут как константа. Теперь понадобилось чтобы данный атрибут изменялся в зависимости от наличия тех или иных модулей.
"Аттрибут изменялся от наличия тех или иных модулей"

Я помню кто-то уже решал эту задачу в чатике. Решается это так: вы ручками пишете конкретную константу. Потому что если вы не знаете сколько у вас модулей будет в проекте, то где-то у вас проблема
источник