In Ruby, which is very similar to Elixir I do this:
def test
yield
end
test do
puts("sup there")
end
Here, the yield keyword will be replaced by the statements (in this case, puts("sup there"), but inside it I can put pretty much whatever I want) inside the block.
It’s not possible to define a function that does this. You can define a macro that does this, but the behaviour is extremely different to the behaviour in Ruby.
To achieve what you’ve described you would use an anonymous function:
test fn ->
puts("sup there")
end
This is conceptually the same as a block/proc in Ruby.
It works, but the evaluation order won’t entirely match the “Ruby blocks” intuition, especially when things like else get involved:
defmodule DoTest do
def foo(do: x, else: y) do
IO.inspect({x, y}, label: "in foo")
end
end
DoTest.foo do
IO.puts("in do")
else
IO.puts("in else")
end
## prints:
# in do
# in else
# in foo: {:ok, :ok}
The parser makes the transformation from do ... end to do: ... consistently, but plain def always evaluates arguments (versus defmacro which passes arguments as AST)