Pregunta

Some languages like Haskell (or Nemerle) have quasiquotations. I wonder what the “quasi” means and if there also exist “quotations” without the “quasi” part.

¿Fue útil?

Solución

I believe this notion comes from Lisp languages.

Program written in Lisp consists of series of lists of lists of lists etc, like this:

 (defn f [x y] (+ x y))

Because of such uniformity it is possible to represent and manipulate such code as data, so the sequence of characters above is interpreted as literal list. This is very useful feature of Lisps, one of their distinctive features. For convenience Lisp languages allow to 'quote' meaningful sequences, turning them from definitions and expressions into lists. It looks like this:

 '(defn f [x y] (+ x y))

In this case it is a literal list, directly available for destructuring using analogues of Haskell's head and tail and other methods. So, 'quote' means 'make a literal value from the list'.

However, it is not convenient to manipulate lists directly with head- and tail-like functions. It becomes notable when you start writing complex macros or even macro-generating macros. So here comes 'quasiquotation', literally 'almost a quotation'. Usually quasiquotation looks like plain quotation (but with another quote symbol):

`(defn f [x y] (+ x y))

But it is much more powerful thing. In quasiquoted list you can replace arbitrary elements with their actual values from outer scope, essentially obtaining something like patterns. Example:

 (let [z 10] `(defn f [x y] (+ x y ~z)))

Here we are binding value 10 to z variable and then we are substituting it inside quasiquote. This expression yields

 '(defn f [x y] (+ x y 10))

This is simple example; Lisp languages allow doing many other useful things with quasiquotes.

This notion has transferred to other languages which support manipulation with syntax trees. For example, Haskell facility here is Template Haskell, and it fully supports quasiquotation, i.e. creating templates and filling them with values from outer scope. In languages with complex syntax (like Haskell) quasi- and plain quotations become nearly the only sane way to manipulate syntax trees.

UPD: hmm, it seems that in Haskell it is more sophisticated feature than simple substitution. Quasiquote in Haskell looks like arbitrary transformer and evaluator of expressions which can be defined by user.

Otros consejos

These notions exist in the Lisp language and its variants.

In these languages, whenever the interpreter sees a list (a b c ... z), it evaluates it, by applying a to the other elements b ... z.

If you want a list not to be evaluated (and thus to be interpreted as a list), you must quote it. For instance, '(a b c) evaluates as a list with three elements, not as a applied to b and c. You can see the quote as stopping evaluation.

Now quasiquotation behaves like quotation, except that you can resume the evaluation inside parts of the list. You quasiquote with the backward apostrophe ` and you allow certain subexpressions to be unquoted with the comma operator (at least in Scheme, I don't know about other Lisp variants). For instance

`(a ,(b c))

evaluates to a list with two elements: a, and the result of the evaluation of (b c).

This is particularly useful to build templates, where you fill holes by unquoting. Example (taken from there):

(define (create-shipping-employee-association name)
  `((name ,name)
    (employee-id-no ,(get-next-employee-id!))
    (department shipping)
    (hire-date ,(get-day) ,(get-month) ,(get-year))))

In Nemerle a quasi-quotation is (http://nemerle.org/metaprogramming.pdf):

"

Meta-language is a language for programming such operations. It usually has its own syntax for describing various constructs of the object language.

For example, in our system:

<[ 1 + f (2 * x) ]>

denotes the syntax tree of expression:

1 + f (2 * x)

This idea is called quasi-quotation.

The prefix quasi comes from the possibility of inserting values of meta-language expressions into the quoted context.

if g(y) is such an expression, we can write:

<[ 1 + $(g(y)) ]>

which describes a syntax tree, whose second part is replaced by the result of evaluation of g(y)

"

A quotation is just a string literal. Quasiquotes are "quoted" in the sense that they represent the input in some sense rather than being compiled code; they just represent it in a form that is easier to manipulate from inside the compilation process (an abstract syntax tree, which you can graft in various ways that are somewhat safer than operating on text).

Quasi basically means that you can put a dollar sign inside the quotation, and switch to the non-quoted code again:

<[ WriteLine( $(ReadLine()) ) ]>

This will output in run-time a string entered in compile-time (actually I don't think this will work e. g. in Visual Studio, since ReadLine requires console input; but you can read from files, network and so on).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top