an attempt at 2d documentation

This commit is contained in:
Robby Findler 2013-03-12 14:37:51 -05:00
parent 8adbd7e836
commit bb0795c502

View File

@ -2,13 +2,14 @@
@(require scribble/base
scribble/manual
"utils.rkt"
scribble/core
(for-label ;unstable/2d/cond
;unstable/2d/match
racket/file
racket/contract
racket/base))
@title[#:tag "2d"]{2D Cond and Match}
@title[#:tag "2d"]{2D Syntax}
@defmodulelang[unstable/2d]{The @racketmodname[unstable/2d] language installs
@litchar{#2d} reader support in the readtable, and then chains to the reader of
@ -16,24 +17,24 @@ another language that is specified immediately after
@racketmodname[unstable/2d].}
The @litchar{#2d} syntax extension adds the ability use
two dimensional grid syntax. That is, you can drawn an ASCII-art
grid and then treat that as a conditional expression. For example,
a two-dimensional grid syntax. That is, you can drawn an ASCII-art
grid and then treat that as an expression. For example,
here is a simple equality function that operates on pairs and
numbers:
numbers, written using a @litchar{#2d} conditional expression:
@codeblock{
#lang unstable/2d racket
(define (same? a b)
#2dcond
╔═════════════╦═══════════════════════╦═════════════╗
║ ║ (pair? a) ║ (number? a) ║
║ ║ (pair? a) ║ (number? a) ║
╠═════════════╬═══════════════════════╬═════════════╣
║ (pair? b) ║ (and (same? (car a) ║ #f ║
║ ║ (car b)) ║ ║
║ ║ (same? (cdr a) ║ ║
║ ║ (cdr b))) ║ ║
╠═════════════╬═══════════════════════╬═════════════╣
║ (number? b) ║ #f ║ (= a b) ║
║ (number? b) ║ #f ║ (= a b) ║
╚═════════════╩═══════════════════════╩═════════════╝)
}
@ -48,16 +49,134 @@ produce a sequence whose first position is the identifier @racket[2dcond].
That macro will take over and then expand into ordinary conditional
expressions, in this case figuring out whether or not the inputs
are pairs or numbers and selecting the appropriate cell.
are pairs or numbers and evaluating the code in the appropriate cell.
At the reader level, the syntax @litchar{#2d} notation checks
the number of columns in the first row and uses that as a guide
for where subsequent rows may appear. Once that first row is set,
it serves as a guide to where the columns may appear in subsequent
rows, although following columns may be merged.
This merging can simplify
some uses of @litchar{#2d} expressions. For example, consider this
expression that captures subtyping relationships between a few of the
Typed Racket numeric types, this time using a @litchar{#2d} match
expression:
@codeblock{
#lang unstable/2d racket
(define (subtype? a b)
#2dmatch
╔══════════╦══════════╦═══════╦══════════╗
║ a b ║ 'Integer ║ 'Real ║ 'Complex ║
╠══════════╬══════════╩═══════╩══════════╣
║ 'Integer ║ #t ║
╠══════════╬══════════╗ ║
║ 'Real ║ ║ ║
╠══════════╣ ╚═══════╗ ║
║ 'Complex ║ #f ║ ║
╚══════════╩══════════════════╩══════════╝)
}
There are a number of cell walls missing here, but this is still a
well-formed @litchar{#2d} expression. In this case, the @racket[2dmatch]
treats any of the situations that fall into the larger regions as
the same.
@section{2D Cond}
@defmodule[unstable/2d/cond]
@defform[(2dcond . stuff)]{}
@defform/subs[(2dcond cond-content)
([cond-content (code:line question-row
body-row
⋮)]
[question-row (code:line empty-cell question-cell ⋯)]
[body-row (code:line question-cell exprs-cell ⋯)]
[question-cell (code:line ╔═════════════╗
║question-expr║
╚═════════════╝)]
[empty-cell (code:line ╔═══╗
║ ║
╚═══╝)]
[exprs-cell (code:line ╔═════════════╗
║expr expr ...║
╚═════════════╝)])]{
Evaluates the first row of question expressions until
one of them returns a true value (signaling an error if none do),
then evaluates the first column of question expressions until
one of them returns a true value (signaling an error if none do),
and then evaluates the cell in the middle where both point to,
returning the result of the last expression in that cell.
}
@section{2D Match}
@defmodule[unstable/2d/match]
@defform[(2dmatch . stuff)]{}
@defform/subs[(2dmatch match-content)
([match-content (code:line match-first-row
match-row
⋮)]
[match-first-row (code:line two-expr-cell match-pat-cell ⋯)]
[match-row (code:line match-pat-cell exprs-cell ⋯)]
[two-expr-cell (code:line ╔═════════════════╗
║col-expr row-expr║
╚═════════════════╝)]
[match-pat-cell (code:line ╔═════╗
║ pat ║
╚═════╝)]
[exprs-cell (code:line ╔═════════════╗
║expr expr ...║
╚═════════════╝)])]{
Matches @racket[col-expr] against each of patterns
in the first column of the table and matches @racket[row-expr]
against each of the patterns in the row row, and then evaluates
the corresponding @racket[exprs-cell], returning the value of the
last expression in that cell.
}
@section{2D Tabular}
@defmodule[unstable/2d/tabular]
@defform/subs[(2dmatch tabular-content)
([tabular-content (code:line tabular-row
⋮)
(code:line tabular-row
style-cell)]
[tabular-row (code:line tabular-cell ⋯)]
[tabular-cell (code:line ╔════════════════╗
║tabular-expr ...║
╚════════════════╝)]
[style-cell (code:line ╔═════════════════╗
║style-content ...║
╚═════════════════╝)]
[style-content (code:line #:style style-expr)
(code:line #:sep sep-expr)
#:ignore-first-row])
#:contracts ([style-expr style?]
[sep-expr (or/c block? content? #f)]
[tabular-expr (or/c block? content?)])]{
Constructs a @racket[tabular] matching the given cells.
If a cell spans multiple columns, then the resulting
@racket[tabular] has @racket['cont] in the corresponding
list element. No cells may span rows.
The @racket[#:style] and @racket[#:sep] arguments are just passed
to @racket[tabular].
If the @racket[#:ignore-first-row] keyword is provided, then the first
row of the @racket[2dtabular] expression is ignored. This can be used
in case the first row of the rendered table should not have all of the
columns (as @litchar{#2d} syntax requires that the first row contain
a cell for each column that appears in the table).
}