Skip to content

Instantly share code, notes, and snippets.

@pcewing
Last active July 10, 2016 22:35
Show Gist options
  • Save pcewing/f9b26131fddbb37807253e64882479cd to your computer and use it in GitHub Desktop.
Save pcewing/f9b26131fddbb37807253e64882479cd to your computer and use it in GitHub Desktop.
Macro Question
# Exercise: MacrosAndCodeEvaluation-2
# Write a macro called *times_n* that takes a single numeric argument. It should define a function
# called *times_n* in the caller's module that itself takes a single argument, and that multiplies
# the argument by *n*. So, calling *times_n(3)* should create a function called *times_3*, and
# calling *times_3(4)* should return 12. Here's an example of it in use:
#
# defmodule Test do
# require Times
# Times.times_n(3)
# Times.times_n(4)
# end
#
# IO.puts Test.times_3(4) #=> 12
# IO.puts Test.times_4(5) #=> 20
#
defmodule Times do
defmacro times_n(n) do
func_name = "times_#{n}"
quote do
def unquote(func_name)(x) do
x * unquote(n)
end
end
end
end
defmodule Test do
require Times
Times.times_n(3) # CompileError: invalid syntax in def "times_3"(x)
end
@pcewing
Copy link
Author

pcewing commented Jul 10, 2016

Changing the line:

func_name = "times_#{n}"

to:

func_name = String.to_atom("times_#{n}")

Resolves the CompileError. This makes sense now that I think about it because the macro was essentially generating:

def "times_3"(x) do

If I understand correctly, function names are implicitly defined atoms, hence why start_link functions support parameters like (MyModule, :func).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment