metaprogramming


Elixir - How can I unquote an array of functions in my macro?


Disclaimer: I know that it's possible to write code in a simpler manner, but you should understand that I post simplified code to SO.
I have a module Simple which uses Included:
defmodule Simple do
use Included,
events: [
[
name: :start,
callback: fn(x) -> x * 2 end
], [
name: :finish,,
callback: fn(x) -> x * 3 ; x end
]
]
end
I want Included module to define a function which takes one param for each item in the list above and return a value. So, I'm doing this:
defmodule Included do
defmacro __using__(opts)
events = Keyword.get(opts, :events)
quote bind_quoted: [events: events] do
events
|> Enum.each(fn(event) ->
def unquote(event[:name])(x) do
x
|> unquote(event[:callback]).()
|> IO.puts
end)
end
end
end
The problem here is that I receive invalid quoted expression: #Function<0.105634730. I tried to implement it another way:
defmodule Included do
defmacro __using__(opts)
events = Keyword.get(opts, :events)
events
|> Enum.each(fn(event) ->
quote bind_quoted: [event: event] do
def unquote(event[:name])(x) do
x
|> event[:callback].()
|> IO.puts
end
end
end)
end
end
But in this case I haven't seen functions defined. (No errors, there is no functions Simple.start/1 and Simple.finish/1 here).
My questions are:
How can I define desired functions?
Why did functions not defined in 2nd approach?
I'm not 100% sure why, but inside the quote in Included.__using__/1, the AST of the function is being converted into an actual function. If you add IO.inspect(events) at the start of the quote, you'll get:
[[name: :start, callback: #Function<0.18558591 in file:c.exs>],
[name: :finish, callback: #Function<1.18558591 in file:c.exs>]]
A workaround I found for this is to escape the :callback in the events.
defmacro __using__(opts) do
events = for event <- opts[:events] do
Keyword.update!(event, :callback, &Macro.escape/1)
end
quote bind_quoted: [events: events] do
...
end
Final code:
defmodule Included do
defmacro __using__(opts) do
events = for event <- opts[:events] do
Keyword.update!(event, :callback, &Macro.escape/1)
end
quote bind_quoted: [events: events] do
events
|> Enum.each(fn(event) ->
def unquote(event[:name])(x) do
x
|> unquote(event[:callback]).()
|> IO.puts
end
end)
end
end
end
defmodule Simple do
use Included,
events: [
[
name: :start,
callback: fn(x) -> x * 2 end
], [
name: :finish,
callback: fn(x) -> x * 3 ; x end
]
]
end
Simple.start 10
Simple.finish 10
Output:
20
10

Related Links

How to define a partial copy constructor metaprogramically in Julia?
How to interpolate into a Julia “for” expression?
Sending a keyword list to a macro and using bind_quoted
Runtime meta programming in ceylon
Is there a fast way of going from a symbol to a function call in Julia? [duplicate]
Programmatically alter Elixir Code
Elixir - How can I unquote an array of functions in my macro?
Nim reflect on type's field types at compile-time
Save variables to file at runtime
In Julia, is it possible to pass values for evaluation in an Expr object without using global variables?
Metaprogramming in Julia — Splice integer into variable name
What's the difference between `use` and `#before_compile`?
How to define functions based on attribute to elixir?
Remove a const qualifier from a variable in D
Meta-modeling crud FROM/JOIN/WHERE statement fragments for higher-level analysis
Elixir: eval'ing code in module context using Code.eval_quoted/3

Categories

HOME
phantom-dsl
scikit-learn
object
powerpoint
swt
sublimetext
grafana
entity-framework-core
nsbundle
tail
settings
x264
polling
jquery-ui
crystal-reports-2013
nstableheaderview
barcode
accessibility
categorical-data
why3
filechannel
pybossa
enterprise-architect
cumulocity
mvc-mini-profiler
easyphp
boost-icl
charles
systemtime
imageresizer
tosca
flask-sqlalchemy
siri
maze
opentk
angularjs-components
android-maps
handler
subclass
scrollview
dotspatial
xbox
powershell-ise
jbutton
glib
laravel-eloquent
clickjacking
code-snippets
reverse
processwire
servicestack-text
hivemq
reason
railstutorial.org
demo
spring-mvc-test
visa
plr
outputcache
avcapturedevice
memory-mapping
git-flow
skin
er-diagram
oozie-coordinator
seq
java-websocket
template-toolkit
renaming
rocks
stripe-connect
cronexpression
xcode-server
segment-io
dotnetnuke-7
neon
signalr.client
hclust
android-dateutils
appscale
freepbx
mediametadataretriever
cda
turbo-prolog
sklearn-pandas
libvlc
vhosts
boomerang
qt5.2
iokit
video-player
text-search
evolus-pencil
lasso
eoferror
rdflib
airbrake
umlgraph
broadband
mass-assignment
theos
cosine-similarity
packet-sniffers
administration
webfinger
insight.database
unix-socket
functional-java
dct
hibernate-entitymanager
script#
apache-abdera
device-width
web-notifications
pdfviewer
kqueue
cgimage
catransform3d
event-receiver
appledoc
qglwidget
rowlex
fault-tolerance
fdf
unmanagedresources
cardspace

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App