4 ms·
Argh. Odd statements about "Erlang was implemented in Prolog, therefore, it's an FP language" aside, I was interested to read more on Elixir's meta-programming,
by EdwardDiego 7y ago
Argh. Odd statements about "Erlang was implemented in Prolog, therefore, it's an FP language" aside, I was interested to read more on Elixir's meta-programming, and was assured that this code was a great example[1]. But there was no further discussion, just a Github link.
For anyone else wondering the same, the Elixir docs give more insight into quote/unquote[2]...
...but I'm still unsure as to why the Unicode code uses it. Most of the time it's unquoting byte_size - but why does what looks like a function call need to be unquoted?
It looks like it's defining the same function with different pattern matching clauses using it, e.g.,
for codepoint <- cluster["CR"] ++ cluster["LF"] ++ cluster["Control"] do
def next_grapheme_size(<<unquote(codepoint), rest::binary>>) do
{unquote(byte_size(codepoint)), rest}
end
end
Would define next_grapheme_size with an arg pattern that matches each code point, effectively creating a pattern match switch without boilerplating it? I think? Keen to hear from someone who knows Elixir.
But yeah, some more detail on a) what it's doing and b) why it's awesome would've been nice.
[1]: https://github.com/elixir-lang/elixir/blob/0d32ea6bc4bcbd626de98b2e2b493a42a4423992/lib/elixir/unicode/unicode.ex https://github.com/elixir-lang/elixir/blob/0d32ea6bc4bcbd626...
[2]: https://elixir-lang.org/getting-started/meta/quote-and-unquote.html https://elixir-lang.org/getting-started/meta/quote-and-unquo...
- elevader 7y agoThe unquote in your code example doesn't necessarily need to be unquoted, it would be enough to unquote the codepoint variable here. The point, I guess, is about at what point you want to evaluate the code. There is a great little function called Macro.to_string that might make this more clear: Macro.to_string(quote do: length([1,2,3])) will return "length([1,2,3])", so it basically creates a macro that, if included in some code, will calculate the length of the list [1,2,3] at runtime. Macro.to_string(quote do: unquote(length([1,2,3]))) will return "3" instead, it basically executes the length function at compile time and then the macro will simply return that if called. So the code example you provided basically calculates the byte size at compile time and will then only return static results at runtime.
- EdwardDiego 7y agoThanks! That makes it clearer. So presumably the for loop it's nested in is also evaluated at compile time?
- elevader 7y agoYes, exactly. This code basically runs at compile time and creates functions that return static results. This case doesn't have to be wrapped inside of the quote thing (I'm not even sure if it would compile if you did...), which is somewhat confusing in my opinion.
- dnautics 7y agoRecently i've been writing a lot of compile-time checks in elixir's metaprogramming, like verifying that compile-time configuration TOML files are correct. One way to think about it is that it's an in-line plugin system for your compiler. It's fantastic that the metaprogramming language is the same as the programming language.