I think Elixir is a bad example here because it's one of the eco systems that, while they preach "Use a function if you can!" very loudly, use macros much more heavily than other eco systems, often in places where they don't have to. Phoenix, the (unfortunate) flagship library, abuses macros all over the place where even relative beginners can see that they didn't need to (see [0] for example). It's incredibly badly designed overall and these things have set the tone (especially since a lot of Elixir programmers are in reality just Phoenix programmers).
So, while macros are "discouraged" in Elixir, in practice they are very much encouraged by several prominent libraries. Picking on Phoenix is very easy because it's so blatantly bad in this regard (and others) but it's almost impossible to do useful things with Ecto if you go outside the macro bubble, etc., as well.
Example that shows how an eco system that definitely could have done stuff with macros (Clojure) has correctly decided that writing functions that take data is better than using macros:
Elixir and `Plug.Router`:
defmodule MyRouter do
use Plug.Router
plug :match
plug :dispatch
get "/hello" do
send_resp(conn, 200, "world")
end
forward "/users", to: UsersRouter
match _ do
send_resp(conn, 404, "oops")
end
end
Clojure and `reitit` (
https://github.com/metosin/reitit):
(def router
(r/routes
[["/hello" {:get (fn [r] {:status 200 :body "world"})}]
["/users" {:name :users
:router users-router}]
["*" {:get (fn [r] {:status 404 :body "oops"})}]]))
P.S. I've used Elixir since 2015, this is not an opinion I've developed at a glance.