In order to learn Elixir macros better, I superficially reimplemented a part of Ecto.Migration, peeking at the original implementation:
https://gist.github.com/henrik/25516815e6680e1c7a82
For the purposes of this question, let's assume it only makes sense to call "add/2" within a "create table(:foo) do" block (I have no idea if that's actually true of Ecto).
The way this is currently implemented in my Gist (and, I think, the way it's implemented in Ecto), the function is available to be called elsewhere as well:
defmodule MyMigration do
use Ecto.Migration
add :can_be_called_here, :string
def change do
add :can_also_be_called_here, :foo
create table(:foo) do
add :name, :string
end
end
end
If this had been a Ruby DSL, one would probably have used instance_eval to make an "add" method available only within that block and nowhere else.
Two questions:
1. Whether or not this is a good idea – just for the sake of learning the boundaries – can this technically be achieved in Elixir? Would one have to do some seriously evil AST slicing-and-dicing?
2. Is there a philosophical difference between Ruby/Elixir or OO/functional in this? Is it unidiomatic and indicative of a more OO-centric, less functional, view of things to consider where this function is available?