#lang scribble/doc @(require "common.ss") @(define (blit s) (schemeparenfont s)) @title[#:tag "at-sign"]{Scribble's @lit["@"] Notation} Scribble's @lit["@"] notation is an alternative syntax for S-expressions that is nicer for writing free-form text. Authors of Scribble documentation use this @lit["@"] notation to make reading and writing documentation source more convenient: @itemize[ @item{A @lit["@"]@nonterm{op}@blit["{"]...@blit["}"] sequence applies @nonterm{op} to text-mode arguments. For example, @scr:code-elem["@emph{programming language}"] applies the @scheme[emph] function to the string @scheme["programming language"], and @scr:code-elem["@section{Welcome to PLT Scheme}"] applies the @scheme[section] function to the string @scheme["Welcome to PLT Scheme"]. Many functions applied this way produce elements for use in a text stream. For example, @scheme[emph] and @scheme[bold] produce @scheme[element] instances. The @scheme[section] function, however, produces a section delimiter, and @scheme[item] produces an intermediate value that wraps a flow to be used in an @scheme[itemization]. These results are independent of the @lit["@"]@nonterm{op}@blit["{"]...@blit["}"] notation, which merely determines the way that the arguments to @nonterm{op} are parsed. The translation of @lit["@"]@nonterm{op}@blit["{"]...@blit["}"] generates multiple arguments to @nonterm{op} if the content of the braces is not a plain string on a single line. For example, @scr:code-elem["@section{country @emph{and} western}"] is equivalent to @scheme[(section "country " (emph "and") " western")]. Passing multiple arguments (instead of collecting them into a list) meshes well with Scheme's support for functions that accept any number of arguments.} @item{A @lit["@"]@nonterm{op}@blit["["]...@blit["]"] sequence applies @nonterm{op} to S-expression arguments. For example, @scr:code-elem|{@itemize[(item "a") (item "b")]}| applies @scheme[itemize] to @scheme[(item "a")] and @scheme[(item "b")]. Since @lit["@"] notation can be used for any S-expression, the @scheme[itemize] call can be written equivalently as @scr:code-elem["@itemize[@item{a} @item{b}]"]. The @nonterm{op} in a @lit["@"]@nonterm{op}@blit["["]...@blit["]"] form can be a Scheme macro instead of a function. For example, @scr:code-elem["@scheme[(lambda (x) x)]"] produces the typeset output @scheme[(lambda (x) x)], because @scheme[scheme] is a macro that uses its argument's syntax, as opposed to a function that would receive the identity function. Again, the @lit["@"] notation is agnostic with respect to the underlying S-expression forms; it merely provides an alternate way to write them.} @item{A @lit["@"]@nonterm{op}@blit["["]...@blit["]"]@blit["{"]...@blit["}"] sequence combines S-expression arguments and text-mode arguments. For example, the @scheme[schemelink] macro hyperlinks a text range to the documentation for a given binding; the bound identifier is supplied first, followed by the text to hyperlink, so @scr:code-elem|{@schemelink[lambda]{anonymous functions}}| produces the text ``anonymous functions'' with a hyperlink to the documentation for @scheme[lambda]. More commonly, the @lit["@"]@nonterm{op}@blit["["]...@blit["]"]@blit["{"]...@blit["}"] form is used to provide optional keyword arguments. For example, the @scheme[section] function accepts an optional argument using the @scheme[#:tag] keyword to set the hyperlink tag for the section, so that @scr:code-elem|{@section[#:tag "intro"]{Welcome to PLT Scheme}}| starts a section whose hyperlink tag is @scheme["intro"].} @item{A @lit["@"]@nonterm{op} sequence without an immediately following @blit["{"] or @blit["["] is equivalent to just @nonterm{op}. This form is used to escape from text mode to S-expression mode. For example, @scr:code-elem|{@(require scribble/manual)}| inserts a @scheme[(require scheme/manual)] form within a document that is otherwise in text mode. Such an import declaration could also be written @scr:code-elem["@require[scribble/manual]"], but by convention, @lit["@"]@nonterm{op}@blit["["]...@blit["]"] is used to imply a typesetting operation, whereas @lit["@"]@nonterm{op} more directly implies an escape to Scheme-programming mode.} ] As illustrated by some of the examples, @lit["@"] notation works the same in both text and S-expression contexts. That is, in a text context, @lit["@"] effectively escapes to S-expression mode, but @lit["@"] notation can be used directly within S-expression mode, too. As a result, typesetting forms that are designed to work best in text mode can also be used in S-expression mode without first escaping to text mode, which significantly reduces the need for explicit quoting/unquoting operations and helps avoid bugs due to incorrect quoting levels. Scribble's @lit["@"] notation builds on the benefits of S-expressions while extending them to better support text. The notation is crucial to Scribble's flexibility in the same way that S-expressions are crucial to Scheme's flexibility---and, in the same way, the benefit is difficult to quantify. The extended notation sets up some undesirable puns, such as the fact that @scheme[(lambda (x) "hello")] could be written as @scr:code-elem|{@lambda[(x)]{hello}}| in addition to @code-elem|{(lambda . ((x) . ("hello")))}|, but such puns reflect an ease of term manipulation that more than compensates for the drawbacks. Furthermore, just as S-expressions can be used for more than writing Scheme programs, the @lit["@"] notation can be used for purposes other than documentation, and the @lit["@"]-notation parser is available for use in PLT Scheme separate from the rest of the Scribble infrastructure. We use it as an alternative to HTML for building the @tt{www.plt-scheme.org} web pages, and we use it as an alternative to @exec{cpp} or @exec{m4} for generating some plain-text documents.