diff --git a/collects/unstable/scribblings/2d.scrbl b/collects/unstable/scribblings/2d.scrbl index d58ed0ec77..7d48d6e09f 100644 --- a/collects/unstable/scribblings/2d.scrbl +++ b/collects/unstable/scribblings/2d.scrbl @@ -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). +}