I hear you, I am curious to know why it can't be done. "Idiomatic" code comes from the capabilities of the language, I don't disagree with you, but we didn't have `with` at some point as well.
I notice that we do a lot of macros to initialize module attrs, or include other macros, and sometimes, we do it only to use one macro in some way (yes, I understand that I can use `require`) Not sure, I dont need it 1000%, but it is nice to have it honestly, there is more cohesion (sometimes) among why `use` and the intention. P.S: I may move with what I have today, or do something around what aditya7 proposed On Monday, August 9, 2021 at 12:58:14 AM UTC-4 Paul Schoenfelder wrote: > Sorry, for some reason I completely overlooked that you were doing this > with `use`. I would second the recommendation to avoid that approach. Since > `use` is a special form, it’s likely you can’t do what you’re trying to do > here anyway. The bigger issue is that it’s very unidiomatic - while it > might save you one extra line of code versus an explicit macro, it’s very > different from how most libraries expose this kind of functionality, and > much less composable. > > Ultimately though, I think you’ll be limited by the fact that `use` is a > special form (IIRC, I haven’t confirmed that you _can’t_ do what you’re > trying to do, but I suspect that’s the thing tripping you up). > > On Mon, Aug 9, 2021, at 12:42 AM, Yordis Prieto wrote: > > aditya7, I dont disagree with you. > > There is always a balance between magic and verbosity. The reason I don't > mind "magic" in Elixir is that everything is explicit and macros are > expanded at compile time. So my intention is to make the code as simple as > possible at the cost of hidden complexity that I am OK with it at the > moment. Everything with balance, this is one of those cases where it is > just a bag of data and few things, the easier the better. > > In the worst case, I will end up doing a version of what you proposed, I > am trying to avoid having to import a module and having to call yet another > function at the moment. > On Monday, August 9, 2021 at 12:35:26 AM UTC-4 Yordis Prieto wrote: > > Hey Paul, > > I can't remove the comma from it thou, I get the following error, `use` > macro expects 2 arguments as far as I can tell > > ``` > ** (ArgumentError) invalid arguments for use, expected a compile time atom > or alias, got: Command[[aggregate_identifier: :id]] > (elixir 1.11.2) lib/kernel.ex:5006: anonymous fn/3 in > Kernel."MACRO-use"/3 > (elixir 1.11.2) lib/enum.ex:1399: Enum."-map/2-lists^map/1-0-"/2 > (elixir 1.11.2) expanding macro: Kernel.use/2 > ``` > > On Sunday, August 8, 2021 at 8:59:03 PM UTC-4 Paul Schoenfelder wrote: > > > It looks to me like the error is due to a stray comma: `use Command, > [aggregate_identifier: :id] do` should be `use Command > [aggregate_identifier: :id] do`, which should work as you’d expect. > > As an aside, you might be interested in > https://github.com/bitwalker/strukt, which looks like it has a lot of > overlap with what you’re building (though what you are shooting for may be > totally different, I just see some similarities) > > Paul > > On Sun, Aug 8, 2021, at 7:54 PM, Adi wrote: > > I am not sure if supporting use/* is the right way forward here. The > `Kernel.use/2` macro is reserved for invoking a module's `__using__/1` > macro. To be honest, I don't like the fact that you're setting the module > attributes and defining the `embedded_schema` in the same macro. You can > easily just define the `@primary_key` in the `__using__/1` macro and > explicitly define the `embedded_schema` in `CreateRecurringTransfer` > itself, but that's my preference. > > Either way, if you have defined a `__using__/3` macro, you can always > invoke it explicitly. Although I would rename it to avoid any confusion for > developers reading the code in the future and potentially thinking it has > something to do with `Kernel.use/2`. > > defmodule Command do > defmacro aggregate_schema(opts \\ [], do: block) do > unless Keyword.has_key?(opts, :aggregate_identifier) do > raise ArgumentError, "Missing :aggregate_identifier key" > end > > aggregate_identifier = Keyword.fetch!(opts, :aggregate_identifier) > > quote do > use Ecto.Schema > @primary_key { @aggregate_identifier_key, :binary_id, autogenerate: > true } > @derive Jason.Encoder > embedded_schema unquote(block) > end > end > end > > defmodule CreateRecurringTransfer do > require Command > Command.aggregate_schema [aggregate_identifier: :id] do > field(:dtstart, :naive_datetime) > field(:dtend, :naive_datetime) > embeds_one(:amount, PositiveAmount) > embeds_one(:rrule, Rrule) > embeds_one(:owned_by, CustomerIdentity) > embeds_one(:from_account, TransferAccount) > embeds_one(:to_account, TransferAccount) > end > end > > On Sunday, 8 August 2021 at 16:15:59 UTC-4 [email protected] wrote: > > I am trying to do the following, > > defmodule Command do > defmacro __using__(opts \\ [], do: block) do > unless Keyword.has_key?(opts, :aggregate_identifier) do > raise ArgumentError, "Missing :aggregate_identifier key" > end > > aggregate_identifier = Keyword.fetch!(opts, :aggregate_identifier) > > quote do > use Ecto.Schema > @primary_key { @aggregate_identifier_key, :binary_id, autogenerate: > true } > @derive Jason.Encoder > embedded_schema unquote(block) > end > end > end > > > Just so I can do something like, > > defmodule CreateRecurringTransfer do > use Command, [aggregate_identifier: :id] do > field(:dtstart, :naive_datetime) > field(:dtend, :naive_datetime) > embeds_one(:amount, PositiveAmount) > embeds_one(:rrule, Rrule) > embeds_one(:owned_by, CustomerIdentity) > embeds_one(:from_account, TransferAccount) > embeds_one(:to_account, TransferAccount) > end > end > > But I get `** (CompileError) iex:3: undefined function use/3` which I > assume what I am trying to do is not supported. > > I am curious to understand why it doesn't work (beside maybe not being > supported), and what would be the problem by trying to support it > > > -- > You received this message because you are subscribed to the Google Groups > "elixir-lang-core" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To view this discussion on the web visit > https://groups.google.com/d/msgid/elixir-lang-core/46c25948-b96e-4982-b710-0ebeae1b5e96n%40googlegroups.com > > <https://groups.google.com/d/msgid/elixir-lang-core/46c25948-b96e-4982-b710-0ebeae1b5e96n%40googlegroups.com?utm_medium=email&utm_source=footer> > . > > > > -- > You received this message because you are subscribed to the Google Groups > "elixir-lang-core" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > > To view this discussion on the web visit > https://groups.google.com/d/msgid/elixir-lang-core/9c80199c-ed64-427a-9d67-12847f9ef8efn%40googlegroups.com > > <https://groups.google.com/d/msgid/elixir-lang-core/9c80199c-ed64-427a-9d67-12847f9ef8efn%40googlegroups.com?utm_medium=email&utm_source=footer> > . > > > -- You received this message because you are subscribed to the Google Groups "elixir-lang-core" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/35527b5d-d835-491b-ba35-1f61968cca8dn%40googlegroups.com.
