Macro for non-null list type

I am seeing this a lot in my code, and it’s begging for a macro: non_null(list_of(non_null(:foo)))

However, this macro doesn’t work:

# schema.ex
  defmacro non_null_list(type) do
    quote do
      non_null(list_of(non_null(unquote(type))))
    end
  end

  query do
    field :foos, non_null_list(:foo) do
      # ...
    end
  end

From reading the stack trace, I guess there’s some expansion magic going on inside field that prevents me from passing my macro as it currently is.

(FunctionClauseError) no function clause matching in Absinthe.Blueprint.TypeReference.unwrap/1    
    
    The following arguments were given to Absinthe.Blueprint.TypeReference.unwrap/1:
    
        # 1
        {:non_null_list, [line: 12], [:foo]}

How would one define a macro that does the trick?

1 Like

@dli your issue is that you can’t use a macro in the same file that you define it. Macros run at compile time, and that means that any macro you want to use has to be compiled first. Put it in a MyAppWeb.Schema.Helpers file and then inside your schema import MyAppWeb.Schema.Helpers.

2 Likes

You could use a private macro defmacrop which would allow you to define it in the same module (which now that I think about it, is an odd inconsistency).

But assuming you want to reuse it across multiple modules, it would make sense to move it into a separate module.

1 Like

I totally forgot about that. Works exactly as designed. Thanks!

Strangely enough, this yields the same error as before. In theory, it should work though. Maybe because we’re useing Absinthe.Schema?