← Back to context

Comment by jimbob45

3 years ago

Is there any Rust outfit out there that doesn't discourage macro use? For that matter, is there any team with a language out there that encourages macro use when working as a team?

I've never seen a team that encouraged writing new macros to solve routine problems. But I've certainly been on teams that made heavy use of a few carefully deployed macros to solve recurring problems specific to that codebase.

I think elixir's sigils are probably the closest thing I've seen to "routine, encouraged macro use." Since almost every application will end up with a bit of template lite almost-dsl pseudo language for something or other. They're simpler than defining a grammar & writing a parser and more maintainable than regex.

  • 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.

So far I've only written rust on solo projects, why is macro use often discouraged? Does that discouragement extend to little things like derive?