1. 34
  1.  

  2. 7

    One significant difference between JSX and quasi-quoting is that Lisp quasiquotes can be nested. To support this, you can mark an unquote to specify how many levels up in the nesting that it works at. So,

       ,foo
    

    means unquote the variable foo in the smallest enclosing quasiquote, while

       ,,foo
    

    means unquote foo in the enclosing quasiquote that is 2 levels up.

    1. 7

      Do you have an example where this sort of shadowing might be used? JSX allows you to arbitrarily nest {} and JSX elements like this (you may need parens around the child JSX elements, I don’t remember off-hand):

      <h1>
        Hello {
          name !== undefined ? 
            <strong>{name}</strong> : 
            <em>[unknown user]</em>
        }
      </h1>
      

      but obviously, there’s no way you could “select” from which scope a substitution is sourced if shadowed.

      1. 3

        Maybe you could use it to generate code that generates data.

        A single quotation generates a list, and unquote lets you insert values:

        $ racket
        > (define x 5)
        > (define y 6)
        > `(1 ,x y)
        '(1 5 y)
        

        A nested quotation generates lists that contain the word “quote” or “quasiquote”

        > (length ``(1 2 3 4 5))
        2
        > (first ``(1 2 3 4 5))
        'quasiquote
        > (second ``(1 2 3 4 5))
        '(1 2 3 4 5)
        

        So you could use single quotation to create data:

        > (define (repeat3 x) `(,x ,x ,x))
        > (repeat3 (+ 2 2))
        '(4 4 4)
        

        and use nested quotation to generate code that generates data:

        > (define (repeat3-macro expr) ``(,,expr ,,expr ,,expr))
        > (repeat3-macro '(+ 2 2))
        '`(,(+ 2 2) ,(+ 2 2) ,(+ 2 2))
        > (eval (repeat3-macro '(+ 2 2)))
        '(4 4 4)
        

        In the body of repeat3-macro, one of the commas is sort of “literal” and ends up in the generated code. And one of the commas is telling it to insert the value of ‘expr’ instead of the literal symbol “expr”.

        1. 1

          Ah, I think I understand the difference here now - what’s being nested is the “quotedness”?

          Thanks for the helpful examples!

      2. 1

        It took me a while to figure out how this nesting works for my Scheme syntax highlighter. Both quasiquote (`) and quasisyntax (#`) nest, but only one at a time. So if you’re within a quasiquote at any depth, a quasisyntax is treated no different from any other quoted symbol (and vice versa).

        Edit: Another thing is that a regular quote (') has no effect on quasiquote nesting, so `',3 evaluates the same as '3, not ',3. It makes sense, but it wasn’t obvious to me before I tried all these edge cases.

      3. 2

        To my mind, templating is related to quasiquoting, but not the same. Quasiquoting occurs within structured data, while templating is essentially string interpolation.

        An interesting variant is golang html/template, which is templating, but is aware of context, in order to provide the correct kind of quoting for the data.

        1. 10

          JSX eventually spits out a templated string but is not itself a template. JSX creates a VDOM and then React or whatever turns that VDOM into an actual string (when doing SSR) or DOM nodes (on the client side).

          1. 1

            Thank you, my mistake, I misread some examples.

          2. 2

            To my mind, templating is related to quasiquoting, but not the same. Quasiquoting occurs within structured data, while templating is essentially string interpolation.

            The biggest reason they aren’t the same is because one operates on Lists, and the other on Strings. In Lisp it’s common to have libraries that allow you to do something like:

            (to-html `(div (span "Here are my favorite links:")
                           (ul
                            ,@(map (lambda (x)
                                     `(li (a ((href ,(link-href x) ,(link-title x)) ,(link-text x))))
                                     links)))))
            

            In this case, there’s an explicit step to stringify it, but it’s not really any different (other than syntax) to string-templating…

            edit: But, of course, the real reason quasi-quoting exists in Lisp is in support of macros, not string templating.

          3. 1

            More or less. I’m working on a language that has quasi-quoting in it, and the first time I showed it to someone they said: “Oh, it’s PHP.”

            So, it’s pretty related, but true quasi-quoting is more powerful of course.