One thing I really like in Elixir is the possibility to generate Elixir code in Elixir without using even macros.
Do you know of any other language with this same capability? For example, such language could be an interesting choice to create satellite nodes of an Elixir/Erlang system.
Ruby where you have for example test which is plain function that creates function.
Lisps, where code is data.
JavaScript where you can dynamically create structures and add methods to the prototypes. Io in the same manner.
AFAIK Python can do that (I have never worked with Python though), for examples see import future
Can we count JIT there? If yes, then almost all compiled languages can use form of the “on the fly” code generation.
Java (annotations) and C# - via reflection
C++ templates are Turing complete
D templates are quite powerful, however some can count that as a cheating, as these are almost macros in Elixir sense
Lua - metatables requires that
Your question is quite broad, as in theory, you can generate any code in any language (as long as both are Turing complete) and compile/interpret it as long as you are able to run compiler/interpreter, which you are able to do if you can run Turing complete code on that machine (just implement compiler/interpreter in language of your choice).
Indeed, any language can be used to generate code in any other language, if not by writting a big string to a file and invoking the compiler of the generated source.
But my question is which other languages do so as elegantly as Elixir does.
But let me reduce the scope a little: and which are not Lisps.
“Elegance” is highly subjective. So still it is hard to tell. We can even argue that Ruby meta programming is “cleaner” as do not require quote/unquote magic. Or that D templates are much better solution, as it almost looks like “regular” code. Or that Rust attributes syntax is much cleaner for end-user together with explicit marks when you use macro (all macro invocations need to end with !).
Also even with Elixir macros you cannot change language syntax, what is possible in some other languages (like Racket or Rust, as long as it is parseable).
Nice one, but consider that it is fully expanded to remove all macros, and then we get pure Elixir code that generates Elixir code, so I think my question still holds.
Or does the “pure Elixir” code the expansion results into, uses strings to build the generated code?
Ok, no strings, so its Elixir generating Erlang code …
See that I refined my question above to “Note that we are not using macros here in the sense that we are not generating code inside a defmacro block .”
elixir compiler generates the code, not elixir itself. We are using macros even if they are not explicit as is the case with defmacro. defmodule, def, etc are all macros. elixir expands them at compile time and then elixir’s compiler translates them into erlang.
function Example() {
let ret = {}
const kv = {
foo: "called foo",
bar: "called bar"
}
for (let name in kv) {
ret[name] = () => kv[name]
}
return ret
}
const example = Example()
console.log(example.foo())
console.log(example.bar())
class Example
{foo: "called foo", bar: "called bar"}.each do |key, value|
define_method(key) { value }
end
end
puts Example.new().foo
puts Example.new().bar
Unfortunately I do not have time to write more examples right now.
This “data structure” is called abstract syntax tree and it is exactly what quote will spit out. So this is tuple in form {element :: atom(), environment :: keyword(), arguments :: term()} (however I do not know how the root of the tree looks like, so maybe someone with more knowledge can say more.
So there is initially a macro expansion phase, then Elixir executes the whole output of this phase, then it picks the resulting AST, and does the normal visit to translate to Erlang code. Is it like this?