[PROPOSAL]: Add support to `IEx.Helpers.import_if_available` for interpolated string arguments

33 views
Skip to first unread message

Kenny Evitt

unread,
Feb 10, 2020, 3:05:59 PM2/10/20
to elixir-lang-core
I recently discovered the wonders of `.iex.exs` files!

But my colleague pointed out that we might want some code, e.g. `import X`, to run only in specific environments. In particular we wanted some code, specifically an `import X`, to NOT run in `:prod`.

I created a post on Elixir Forum about this:


I ended-up with a solution that uses a macro to wrap calls to `import_if_available` so that an interpolated string could be used:

```elixir
  defmacro import_with_interpolation(t) do
    t_string      = Macro.to_string(t)
    {t_evaled, _} = Code.eval_string(t_string)

    quote do
      import_file_if_available unquote(t_evaled)
    end
  end
```

It seems like it would be easy enough to just update the existing `import_if_available`. Or maybe my macro could be added to `IEx.Helpers` separately.

Thoughts? (Problems with my macro code?)

Fernando Tapia Rico

unread,
Feb 11, 2020, 3:21:28 AM2/11/20
to elixir-lang-core
Hi Kenny,

Unfortunately, I think that macro will not work in all the scenarios :( For example:

iex_type = if condition?, do: "foo", else: "bar"
import_with_interpolation
".iex.#{iex_type}.exs"

For you use case, I think you could use a similar macro:

defmacro import_iex_type_file do
  iex_type
= if condition?, do: "foo", else: "bar"
  iex_type_file
= ".iex.#{iex_type}.exs"

  quote
do
    import_file_if_available unquote
(iex_type_file)
 
end
end

Hope that helps :)


Kenny Evitt

unread,
Feb 11, 2020, 10:30:50 AM2/11/20
to elixir-lang-core
Hi Fernando,

Thanks for the feedback!

You're right that the example you provided doesn't work. But maybe there's some way to evaluate within the caller's context (`__CALLER`)?

I tried this:

  defmacro import_with_interpolation(t) do
    t_string      
= Macro.to_string(t)

   
{t_evaled, _} = Code.eval_string(t_string, Macro.Env.vars(__CALLER__), __CALLER__)



    quote
do
      import_file_if_available unquote
(t_evaled)
   
end
 
end


Unfortunately, that doesn't work because `Macro.Env.vars` just returns the variable names, but not their values.

My original macro works for me because I was calling it exactly like this:

import_file_if_available_with_interpolation ".iex.#{Mix.env}.exs"

And `Mix.env` *can* be evaluated in the current environment just fine.

Is there not some way to get both the variables and their current values from the `__CALLER__` context and pass that to `Code.eval_string`?
Reply all
Reply to author
Forward
0 new messages