quote./unquote

114 views
Skip to first unread message

Dave Thomas

unread,
May 22, 2013, 3:08:44 PM5/22/13
to elixir-l...@googlegroups.com
Gentle coders:

I understand the provenance of `quote` and `unquote`, but I'm wondering if perhaps it's a little obscure for a reader coming to Elixir from a nonLisp language. While the quote form is used all over the place in Lisp, and hence makes sense when quoting code, this is the only time it is used in Elixir. When writing about macros, I'm having a hard time justifying the names (particular unquote.

Naming is always difficult, but how about something like:

  defmacro if(condition, clauses) do
    do_clause = Keyword.get(clauses, :do, nil)
    else_clause = Keyword.get(clauses, :else, nil)

    code_generator do
      case insert_code(condition) do
        _ in [false, nil] -> insert_code(else_clause)
        _                 -> insert_code(do_clause)
      end
    end
  end

(Or something... :)

We could keep quote/unquote as aliases.



Dave



Jeremy Huffman

unread,
May 22, 2013, 3:22:13 PM5/22/13
to elixir-l...@googlegroups.com

I have never used Lisp macros and didn't know that was the origin for the names. I still found it pretty straight forward. I can't say exactly what I thought it meant but either way you have to learn how it works.

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Alexei Sholik

unread,
May 22, 2013, 5:30:18 PM5/22/13
to elixir-lang-core
I can't speak from the point of view of a beginner, but I do find those new names misleading.

I think of the code that is wrapped in `quote` as a literal code or template. You create a template that will be used to produce code at each macro invocation. To justify the name "quote", one could imagine that it creates a quote that is then mentioned in other places. Similar to how you would mention a quote from Shakespeare literally where it's appropriate. Calling it "template" would make it less familiar to those who do know about quoting in Lisp (it has been around for more than half a century after all).

For a brief acquaintance with the quoting concept, it's sufficient to remember that it produces a template that is expanded into real code at macro invocations. So you just "quote" a piece of code that will be mentioned in other places. It is important to emphasize this "literalness" of quote because you can't use private functions or local function calls inside quote. If you are aware of the fact that the code inside quote is going to be literally pasted at a macro invocation, then the fact that you can only call public functions/macros using a fully qualified call inside quote starts to make sense more sense.

Now, when thinking about unquote, you need to treat it as a trigger to get out of quote and not as something that unquotes it's argument (whatever that could mean). For instance, in this code sample

    var = [1,2,3]
    quote do
      Enum.map var, &1 * 2
    end

the code inside quote serves as a _literal_ template, so it doesn't know about the var on the first line. What we need here is a way to get out of "quote" for a moment, and "unquote" lets us do exactly that. In the following code

    var = [1,2,3]
    quote do
      Enum.map unquote(var), &1 * 2
    end

"unquote" merely takes us out from quote to be able to use the variable and it pastes the result of evaluating that variable back into the quote. So this is simply a way of stitching together one literal code template from multiple pieces. This implies that whatever is passed to "unquote" should be a template too. And this is true:

    fragment = quote do: IO.puts "Hello world"
    quote do
      unquote(fragment)
    end

is the same as

    quote do
      IO.puts "Hello world"
    end

It might get a bit confusing when you do quote([1,2,3]) and it works. But that is due the fact that (quote do: [1,2,3]) === [1,2,3]. In other words, literal values (binaries, atoms, numbers, lists) result in themselves when being quoted. But the general rule is still the same -- "unquote" simply injects/pastes a quoted fragment at the place of its invocation inside another quote.

This is were I find the name "insert_code" misleading. unquote(IO.puts "Hello world") does not insert the code inside parens as I would have thought by just looking at the name. It simply allows the expression inside parens to be evaluated and the inserts its result into the quote at the place where "unquote" was called.

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Best regards
Alexei Sholik

Alexei Sholik

unread,
May 22, 2013, 5:32:51 PM5/22/13
to elixir-lang-core
...so a more appropriate name for "unquote" could be "evaluate_this_expression_outside_of_quote_context" or "stop_quoting_for_a_second_for_this_expression" but that would be too long.

Saša Jurić

unread,
May 22, 2013, 5:52:42 PM5/22/13
to elixir-l...@googlegroups.com, da...@pragprog.com
I like the quote name, but the unquote really bothers me, because it's long and also because it's not the inversion of the quote.
Perhaps an operator could work better?

var = [1,2,3]
quote do
  Enum.map #{var}, &1 * 2
end

J David Eisenberg

unread,
May 22, 2013, 7:01:54 PM5/22/13
to elixir-l...@googlegroups.com


On Wednesday, May 22, 2013 2:32:51 PM UTC-7, alco wrote:
...so a more appropriate name for "unquote" could be "evaluate_this_expression_outside_of_quote_context" or "stop_quoting_for_a_second_for_this_expression" but that would be too long.

How does "nonquote", "nonquoted", or "notquoted" work for you?

Dave Thomas

unread,
May 22, 2013, 7:57:48 PM5/22/13
to elixir-l...@googlegroups.com

How does "nonquote", "nonquoted", or "notquoted" work for you?


If we are going to change it, I'd rather change it to describe how it is used, and not what it does internally. The word "quote" is an anachronism  (or possibly a tip-of-the-hat) here. 

Dave

Jeremy Huffman

unread,
May 22, 2013, 9:40:07 PM5/22/13
to elixir-l...@googlegroups.com
I like the idea of an operator. I think all the unquotes can get kind of noisy. What kind of operator signifies an escape from the quote?


J David Eisenberg

unread,
May 23, 2013, 1:35:49 AM5/23/13
to elixir-l...@googlegroups.com, da...@pragprog.com

Well, then, I guess that "etouq" won't work for you either :)
 

José Valim

unread,
May 23, 2013, 3:06:17 AM5/23/13
to elixir-l...@googlegroups.com, da...@pragprog.com
Some mentioned that unquote is the opposite of quote. I am going to propose an alternative view to understand how quote and unquote work based on strings.

In order to define a string, you need to a literal quote:

    "hello"

In order to generate Elixir code, you need the quote macro:

    quote do
      hello
    end

In order to introduce something in the middle of a string, you need to unquote it and add your own expressions:

    "hello " <> my_expression <> " world"

Which with interpolation, can be written as:

    "hello #{my_expression} world"

For code generation, we have a way to get out of our quote too, which is called unquote:

    quote do
      hello + unquote(my_expression) + world
    end

So notice how unquote is not about doing the opposite of quote, but getting out of a quote temporarily, to insert some existing code.

There is a programming language Julia and in general they have a very similar macro system to Elixir with a very interesting syntax. In order to generate a quote, you use : in Julia:

    foo # variable foo in Julia
    :foo # atom foo in Julia which also represents the quoted expression of the variable foo

You can define more complex code with:

    :(1 + 2)

And, in order to unquote something, you use the same syntax as string interpolation!

    "hello $string_interpolation world"
    :(1 + $quote_interpolation)

Unfortunately, string interpolation in Elixir is done with #{} which starts a comment. But assuming it was done with %{}, would this code be any clearer:

    "hello %{string_interpolation} world"

    quote do
      1 + %{quote_interpolation}
    end

?


José Valim
Skype: jv.ptec
Founder and Lead Developer


--

Sasa Juric

unread,
May 23, 2013, 3:50:20 AM5/23/13
to elixir-l...@googlegroups.com
I realize that unquote is not the opposite of quote, however its name implies that it is, which seems somewhat misleading. Additionally, the name is verbose, given that complex macros usually perform more frequent unquoting.
So yes, I think %{} might help.
Notice that we need something for unquote_splicing as well.


You received this message because you are subscribed to a topic in the Google Groups "elixir-lang-core" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elixir-lang-core/JyX0dxOR7Zw/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to elixir-lang-co...@googlegroups.com.

José Valim

unread,
May 23, 2013, 3:55:46 AM5/23/13
to elixir-l...@googlegroups.com
I am not a native speaker but I think unquote means literally (end of a quote) and not some action (like remove the quotes in a particular sentence). For example: "He said, quote, you are very elegant today, unquote" - marks the beginning and the end of the quotation.

I particularly don't mind the name being verbose. Macros are already complex. I'd trade clarity over conciseness any day for any macro code.

José Valim
Skype: jv.ptec
Founder and Lead Developer

Sasa Juric

unread,
May 23, 2013, 4:09:25 AM5/23/13
to elixir-l...@googlegroups.com

On May 23, 2013, at 9:55 AM, José Valim wrote:

> I am not a native speaker but I think unquote means literally (end of a quote) and not some action (like remove the quotes in a particular sentence). For example: "He said, quote, you are very elegant today, unquote" - marks the beginning and the end of the quotation.

That's a good remark, however the name is still misleading in the Elixir macro context even with this interpretation.

> I particularly don't mind the name being verbose. Macros are already complex. I'd trade clarity over conciseness any day for any macro code.

While generally I agree with this, I don't find it applies here. I don't think the name unquote adds clarity nor do I think it is concise. Of course, this is only my personal opinion, others might disagree.

Dave Thomas

unread,
May 23, 2013, 8:02:27 AM5/23/13
to elixir-l...@googlegroups.com


In order to introduce something in the middle of a string, you need to unquote it and add your own expressions:

    "hello " <> my_expression <> " world"

That's true. But you also have to concatenate the results together. I'd say both things (turning off code -> ast _and_ the insertion are important, which is why I thought something like `insert_code` might help.

But, if we wanted to use something more like an operator and less like a function call, then how about %i{....} (for insert code)?  Or, it seems like backticks are free to be used

quote do
  if %i{cond} ...

or

quote do
  if `cond`

Just a thought.


Dave

Sasa Juric

unread,
May 23, 2013, 8:08:34 AM5/23/13
to elixir-l...@googlegroups.com
I don't quite like %i{} it starts getting noisy and cryptic, and reminds me a bit of the sigils based lambda macro we discussed a while ago.

The backticks on the other hand seem very elegant and concise.

--
You received this message because you are subscribed to a topic in the Google Groups "elixir-lang-core" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elixir-lang-core/JyX0dxOR7Zw/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to elixir-lang-co...@googlegroups.com.

Jeremy Huffman

unread,
May 23, 2013, 10:27:04 AM5/23/13
to elixir-l...@googlegroups.com

I agree %{} is not pretty but I also agree with Jose that it is good for it to stand out. I think ` is also good and a syntax highlighter will make out stand out.

You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.

Oren Ben-Kiki

unread,
May 23, 2013, 10:33:34 AM5/23/13
to elixir-l...@googlegroups.com
We were toying with the idea of using ` for lambda scoping... With much the same reasoning (%{ ... } being too noisy etc.). I guess there are only so many ASCII characters one can use...
Reply all
Reply to author
Forward
0 new messages