Next: Hash-sets, Previous: Introduction, Up: Top [Contents][Index]
Central to change ringing is permuting sequences of a fixed collection of bells, where
the cardinality of that collection is the stage. For modeling such things Roan
provides the types bell
, stage
and row
, and various operations
on them. It is also provides tools for reading and writing place notation.
• Bells | ||
• Stages | ||
• Rows | ||
• Place notation |
Next: Stages, Up: Fundamental Types [Contents][Index]
Roan supports ringing on as few as 2, or as many as 24, bells. Bells are represented as
small, non-negative integers less than this maximum stage. However, bells as the integers
used in Roan are zero-based: the treble is zero, the tenor on eight is 7, and so on. The
bell
type corresponds to integers in this range. There are functions for mapping
bells to and from the characters corresponding to their usual textual representation in
change ringing.
A representation of a bell. These are zero-based, small integers, so the treble is
0
, the second is 1
, up to the tenor is one less than the stage.
Returns a character denoting this bell, or nil
if bell is not a
bell
. If the character is alphabetic, an upper case letter is returned if the
generalized boolean upper-case is true, and otherwise a lower case letter. If
upper-case is not supplied it defaults to the current value of
*print-bells-upper-case*
.
(bell-name 0) ⇒ #\1 (map 'string #'bell-name (loop for i from 0 below +maximum-stage+ collect i)) ⇒ "1234567890ETABCDFGHJKLMN" (bell-name -1) ⇒ nil (bell-name +maximum-stage+) ⇒ nil
Returns the bell
denoted by the character designator char, or nil
if it is not a character designator denoting a bell. The determination is case-insensitive.
(bell-from-name "8") ⇒ 7 (bell-from-name "E") ⇒ 10 (map 'list #'bell-from-name "135246") ⇒ (0 2 4 1 3 5) (bell-from-name "%") ⇒ nil
When printing bell names that are letters, whether or not to use upper case letters by
default. It is a generalized boolean, with an initial default value of t
.
Next: Rows, Previous: Bells, Up: Fundamental Types [Contents][Index]
The stage
type represents the subset of small, positive integers corresponding to
the numbers of bells Roan supports. While Roan represents stages as small, positive
integers, it is conventional in ringing to refer to them by names, such as “Minor” or
“Caters”. There are functions for mapping stages, the integers used by Roan, to and from
their conventional names as strings.
A supported number of bells, an integer between +minimum-stage+
and
+maximum-stage+
, inclusive.
The smallest number of bells supported, 2.
The largest number of bells supported, 24.
Returns a string, the conventional name for this stage, capitalized, or
nil
if stage is not an integer corresponding to a supported stage.
(stage-name 8) ⇒ "Major" (stage-name 22) ⇒ "Twenty-two" (stage-name (1+ +maximum-stage+)) ⇒ nil
Returns a stage, a small, positive integer, with its name the same as the string
designator name, or, if there is no stage with such a name, nil
. The
determination is made case-insensitively.
(stage-from-name "cinques") ⇒ 11 (stage-from-name "no-such-stage") ⇒ nil
An integer, the default value for optional or keyword arguments to many functions that
must have a stage specified. See write-row
,
row-string
,
write-place-notation
and
place-notation-string
.
Next: Place notation, Previous: Stages, Up: Fundamental Types [Contents][Index]
The fundamental units of change ringing are rows and changes, permutations of a fixed set
of bells. A distinction between them is often made, where a row is a permutation of bells
and a change is a permutation taking one row to the next. In Roan they are both
represented by the same data type, row
; row
s should be treated as immutable.
The Lisp reader can be
augmented by Roan to read row
s printed in the notation usually used by change
ringers by using the ‘!’ reader macro. For example, queens on twelve can be entered
in Lisp as !13579E24680T
. When read with the ‘!’ reader macro bells
represented by alphabetic characters can be either upper or lower case; so queens on
twelve can also be entered as !13579e24680t
or !13579e24680T
.
To support the common case of writing lead heads of treble dominated methods if the treble
is leading it can be omitted. Thus, queens on twelve can also be entered as
!3579E24680T
. Apart from a leading treble, however, if any bell is omitted from a
row written with a leading ‘!’ character an error will be signaled.
Note that row
s are Lisp atoms, and thus literal values can be written using
‘!’ notation without quoting, though quoting row
s read that way will do no
harm when they are evaluated.
This ‘!’ syntax can be turned on and off by using roan-syntax. By default it is off when Roan is loaded. It is also possible to control this syntax by using Named Readtables; see roan-syntax for further details.
Similarly, row
s are printed using this same notation,
*print-escape*
controlling whether or not they are preceded by ‘!’ characters. Note that the
characters used to represent bells in this printed representation differ from the small
integer bell
s used to represent them internally, since the latter are zero based.
For example, the treble is represented internally by the integer 0, but in this printed
representation by the digit character ‘1’. When printing rows in this way a leading
treble is not elided. And *print-bells-upper-case*
can be used to control the case
of bells in the printed representation of row
s that are representated by letters,
in cinques and above.
CL-USER> !12753468 !12753468 CL-USER> '!2753468 !12753468 CL-USER> (format t "with: ~S~%without: ~:*~A~%" !TE0987654123) with: !TE0987654123 without: TE0987654123 NIL CL-USER> (let ((roan:*print-bells-upper-case* nil)) (format nil "~A" !TE0987654123)) "te0987654123" CL-USER>
Rows can be compared for equality using equalp
(but not equal
). That is,
two different row
objects that correspond to the same ordering of the same number of
bells will be equalp
. Hash tables with a :test
of equalp
are often
useful with row
s. See hash-set.
(equalp !13572468 !13572468) ⇒ t (equalp !13572468 !12753468) ⇒ nil (equalp !13572468 !1357246) ⇒ nil (equalp !13572468 !3572468) ⇒ t
A permutation of bells at a particular stage. The type row
is used to represent
both change ringing rows and changes; that is, rows may be permuted by other rows.
Instances of row
should normally be treated as immutable.
Turns on or off the read macros for ‘!’ and ‘#!’, for reading rows and place notation.
If the generalized boolean on-off is true, the default, it turns on these read macros. Unless the generalized boolean modify is false, the default, it first pushes the current read table onto a stack, modifying a copy of it and making that copy the current read table. If modify is true it makes no copy and instead modifies the current readtable in place.
If on-off is false it restores the previous readtable by popping the stack. If the stack is empty it sets the readtable to a new, standard one. When on-off is false modify is ignored.
This is performed in an eval-when
context to ensure it happens at compile time as
well as load and execute time.
An alternative to using roan-syntax
is to use
Named Readtables. Roan defines two
such readtables with names :roan
and :roan+interpol
. The former augments the
initial Common Lisp read table with Roan’s read macros, and the latter also adds the
syntax from CL-INTERPOL.
Non-nil if and only if object is a row
.
The number of bell
s of which the row
row is a permutation.
Writes row, which should be a row
, to the indicated stream.
The case of any bells represented by letters is controlled by upper-case, a
generalized boolean defaulting to the current value of *print-bells-upper-case*
.
escape, a generalized Boolean defaulting to the current value of
*print-escape*
, determines whether or not to write it in a form that read can
understand. Signals a type-error
if row is not a row
, and the usual
errors if stream is not open for writing, etc.
Returns a string representing the row
row. The case of any bells
represented by letters is controlled by upper-case, a generalized
boolean defaulting to the current value of *print-bells-upper-case*
. Signals a
type-error
if row is not a row
.
Constructs and returns a row
from the conventional symbols for bells read from
the stream. The stage of the row read is determined by the bells present, that is by
the largest bell for which a symbol is read. The treble can be elided, in which case it is
assumed to be leading; a parse-error
is signaled if any other bell is omitted.
Bells represented by letters can be either upper or lower case.
Contructs a row
from the conventional symbols for bells in the section of string
string delimited by start and end, possibly preceded or followed by
whitespace. The treble can be elided, in which case it is assumed to be leading; a
parse-error
is signaled if any other bell is omitted. Bells represented by letters
can be either upper or lower case. If string is not a string a type-error
is
signaled. If the generalized boolean junk-allowed is false, the default, an error
will be signaled if additional non-whitespace characters follow the representation of a
row. Returns two values: the row
read and a non-negative integer, the index into
the string of the next character following all those that were parsed, including any
trailing whitespace; if parsing consumed the whole of string, the second value will
be length of string.
Constructs and returns a row
containing the bells, in the order they
appear in the argument list. If the treble is not present, it defaults to being the first
bell in the row. Duplicate bells or bells other than the treble missing result in an error
being signaled.
(row 2 1 3 4 7 6 5) ⇒ !13245876
Returns a row
representing rounds at the given stage, which defaults to
*default-stage*
Signals a type-error
if stage is not a stage
,
that is an integer between +minimum-stage+
and +maximum-stage+
, inclusive.
The bell-at-position
function returns the bell
(that is, a small integer)
at the given position in the row. The position-of-bell
function returns
position of bell in row, or nil
if bell does not appear in
row. The indexing into row is zero-based; so, for example, the leading bell is
at position 0, not 1. Signals an error if row is not a row
, or if
position is not a non-negative integer or is too large for the stage of row
(bell-at-position !13572468 3) ⇒ 6 (bell-name (bell-at-position !13572468 3) ⇒ #\7 (position-of-bell 6 !13572468) ⇒ 3 (position-of-bell (bell-from-name #7) !13572468) ⇒ 3
The bells-list
function returns a fresh list of bell
s (small, non-negative
integers, zero-based), the bells of row, in the same order that they appear in
row. The bells-vector
function returns a vector of bell
s (small,
non-negative integers, zero-based), the bells of row, in the same order that they
appear in row. If vector is not supplied or is nil
a freshly created,
simple general vector is returned.
(bells-list !13572468) ⇒ (0 2 4 6 1 3 5 7) (bells-vector !142536) ⇒ #(0 3 1 4 2 5)
If a non-nil vector is supplied the bell
s are copied into it and it is
returned. If vector is longer than the stage of row only the first elements of
vector, as many as the stage of row, are over-written; the rest are unchanged.
If vector is shorter than the stage of row, then, if it is adjustable, it is
adjusted to be exactly as long as the stage of row, and otherwise an error is
signaled without any modifications made to the contents of vector or its
fill-pointer, if any. If vector has a fill-pointer and is long enough to hold all
the bells of row, possibly after adjustment, its fill-pointer is set to the stage of
row.
A type-error
is signaled if row is not a row
. An error is signled if
vector is neither nil
nor a vector
with an element type that is a
supertype of bell
, and of sufficient length or adjustable.
Returns a row
of the same stage as row with its bells in the reverse
order. A type-error
is signaled if row is not a row
.
(reversed-row !32148765) ⇒ !56784123
• Properties of rows | ||
• Permuting rows |
Next: Permuting rows, Up: Rows [Contents][Index]
True if and only if row is a row
representing rounds at its stage.
(roundsp !23456) ⇒ t (roundsp !123546) ⇒ nil (roundsp 123456) ⇒ nil
True if and only if row is a row
representing a permutation with no
bell moving more than one place.
(changep !214365) ⇒ t (changep !143265) ⇒ nil (changep |214365|) ⇒ nil
Returns true if and only if row is a (non-jump) change, with exactly the specified places being made, and no others. To match a cross at even stages supply no places.
Signals a type-error
if row is not a row
or any of places are
not bell
s. Signals an error
if any of places are not less than the
stage of row, or are duplicated.
(placesp !21354768 2 7) ⇒ t (placesp !21346587 2 7) ⇒ nil (placesp !21354768 2) ⇒ nil (placesp !2135476 2) ⇒ t (placesp !21436587) ⇒ t
True if and only if row is a row
representing an even permutation.
(in-course-p !132546) ⇒ t (in-course-p !214365) ⇒ nil (in-course-p "132546") ⇒ nil
True if and only if row is a row
that is its own inverse.
(involutionp !13248765) ⇒ t (involutionp !13425678) ⇒ nil (involutionp nil) ⇒ nil
Returns a positive integer, the order of row: the minimum number of times it must
be permuted by itself to produce rounds. A type-error
is signaled if row is
not a row
.
(order !13527486) ⇒ 7 (order !31256784) ⇒ 15 (order !12345678) ⇒ 1
Returns a list of lists of bells. Each of the sublists is the orbit of all of its elements in row. One cycles are included. Thus, if row is a lead head, all the sublists of length one are hunt bells, all the rest being working bells; if there are two or more sublists of length greater than one the corresponding method is differential. The resulting sublists are each ordered such that the first bell is the lowest numbered bell in that cycle, and the remaining bells occur in the order in which a bell traverses the cycle. Within the top level list, the sublists are ordered such that the first bell of each sublist appear in ascending numerical order.
(cycles !13572468) ⇒ ((0) (1 4 2) (3 5 6) (7)) (format nil "~{(~{~C~^,~})~^, ~}" (mapcar #'(lambda (x) (mapcar #'bell-name x)) (cycles !13572468))) ⇒ "(1), (2,5,3), (4,6,7), (8)"
Returns true if and only if all the bells of row at positions starting-at
or higher are in their rounds positions. In the degenerate case of starting-at being
equal to or greater than the stage of row it returns true. Note that it is
equivalent to (not (null (alter-stage row starting-at)))
. If not
supplied starting-at defaults to 6
, that is the position of the bell
conventionally called the seven, though represented in Roan by the small integer 6
.
Signals a type-error
if row is not a row
or starting-at is not a
non-negative integer.
(tenors-fixed-p !13254678) ⇒ t (tenors-fixed-p !13254678 5) ⇒ t (tenors-fixed-p !13254678 4) ⇒ nil (tenors-fixed-p !54321) ⇒ t (tenors-fixed-p !54321 4) ⇒ nil
If row is a lead head of a plain course of Plain Bob at its stage returns a
positive integer identifying which lead head it is; returns nil
if row is not
a Plain Bob lead head. If row is the first lead head of a plain course of Plain Bob
1
is returned, if the second 2
, etc. For the purposes of this function
rounds is not a Plain Bob lead head, nor is any row below minimus. Signals a
type-error
if row is not a row
.
(which-plain-bob-lead-head !13527486) ⇒ 1 (which-plain-bob-lead-head !42638507T9E) ⇒ 10 (which-plain-bob-lead-head !129785634) ⇒ nil (which-plain-bob-lead-head !12345) ⇒ nil (which-plain-bob-lead-head !132) ⇒ nil
If row is a lead head of a plain course of Grandsire at its stage returns a
positive integer identifying which lead head it is; returns nil
if row is not
a Grandsire lead head. If row is the first lead head of a plain course of Grandsire
1
is returned, if the second 2
, etc. For the purposes of this function
rounds is not a Grandsire lead head, nor is any row below minimus. Signals a
type-error
if row is not a row
.
(which-plain-bob-lead-head !1253746) ⇒ 1 (which-plain-bob-lead-head !28967453) ⇒ 4 (which-plain-bob-lead-head !135264) ⇒ nil (which-plain-bob-lead-head !1243) ⇒ 1 (which-plain-bob-lead-head !12345) ⇒ nil
Previous: Properties of rows, Up: Rows [Contents][Index]
Permutes row by the changes in turn. That is, row is first permuted by
the first of the changes, then the resuling row is permuted by second of the
changes, and so on. Returns the row resulting from applying all the changes. So long
as one or more changes are supplied the returned row
is always a freshly
created one: row and none of the changes are modified (as you’d expect, since
they are intended to be viewed as immutable). The row and all the changes
should be row
s.
At each step of permuting a row by a change, if the row is of higher stage than the
change, only the first stage bells of the row are permuted, where stage is the
stage of the change, all the remaining bells of the row being unmoved. If the row is of
lower stage than the change, it is as if the row were extended with bells in their rounds’
positions for all the bells stage and above. Thus the result of each permuation step
is a row
whose stage is the larger of those of the row and the change.
If no changes are supplied row
is returned. Signals a type-error
if
row or any of the changes are not row
s.
(permute !34256 !35264) ⇒ !145362 (permute !34125 !4321 !1342) ⇒ !24315 (permute !4321 !654321) ⇒ !651234 (let ((r !13572468)) (list (eq (permute r) r) (equalp (permute r (rounds 8)) r) (eq (permute r (rounds 8)) r))) ⇒ (t t nil)
Permutes each of the elements of a sequence or hash-set
and an
individual row
, collecting the results into a similar collection. The
permute-collection
version permutes each the elements of collection by
change; permute-by-collection
permutes row by each of the elements of
collection by change. The return value is a list, vector or hash-set
if
collection is a list, vector or hash-set
, respectively. The
permute-collection
and permute-by-collection
versions always return a fresh
collection; the npermute-collection
and npermute-by-collection
versions
modify collection, replacing its contents by the permuted rows. If collection
is a sequence the contents of the result are in the same order: that is, the Nth element
of the result is the Nth element supplied in collection permuted by or permuting
change or row. If collection is a vector, permute-collection
and permute-by-collection
always return a simple, general vector.
If the result is a sequence, or if all the elements of collection were of the same
stage as one another, it is guaranteed that the result will be the same length or
cardinality as collection. However, if collection is a hash-set
containing rows of different stages the result may be of lower cardinality than then the
supplied hash-set
, if collection contained two or more elements that were not
equalp
because they were of different stages, but after being permuted by, or
permuting, a higher stage row the results are equalp
.
Signals a type-error
if change, row or any of the elements of
collection are not rows
s, or if collection is not a sequence or
hash-set
.
Generates a sequence of row
s by permuting a starting row
successively by each element of the sequence changes. The elements of changes
should be row
s. If initial-row is supplied it should be a row
. If it
is not supplied, rounds at the same stage as the first element of changes is used;
if changes is empty, rounds at *default-stage*
is used. Two values are
returned. The first is a sequence of the same length as changes, and the second is a
row
. So long as changes is not empty, the first element of the first return
value is initial-row, or the default rounds. The next value is that row
permuted by the first element of changes; then that row
permuted by the next
element of changes, and so on, until all but the last element of changes has
been used. The second return value is the last element of the first return value permuted
by the last element of changes. If changes is empty, then the first return
value is also empty, and initial-row, or the default rounds, is the second return
value. Thus, for most methods, if changes are the changes of a lead, the first
return value will be the rows of a lead starting with initial-row, and the second
return value the lead head of the following lead.
If changes is a list, the first return value is a list; if changes is a
vector, the first return value is a vector. The generate-rows
function always
returns a fresh sequence as its first return value, while ngenerate-rows
resuses
changes, replacing its elements by the permuted rows and returning it. The fresh
vector created and returned by generate-rows
is always a simple, general vector.
Signals an error if initial-row is neither a row
nor nil
, if
changes isn’t a sequence, or if any elements of changes are not
row
s.
(multiple-value-list (generate-rows '(!2143 !1324 !2143 !1324) !4321)) ⇒ ((!4321 !3412 !3142 !1324) !1234)
Returns a list of distinct rows that can be generated by permuting, repeatedly if
necessary, any of the rows by themselves or any others of the rows. If the
rows are not all of the same stage, the lower stage ones are converted to the
highest stage present before the closure operation is performed. The order of the returned
rows is undefined. Signals a type-error
if any of the rows is not a
row
.
(permutation-closure !13425 !1324 !123465) ⇒ (!143265 !142365 !124365 !142356 !143256 !124356 !134265 !132465 !123456 !123465 !132456 !134256)
Returns the inverse of the row
row. That is, the row
, r, such
that when row is permuted by r, the result is rounds. A theorem of group
theory implies also that when r is permuted by row the result will also be
rounds. Signals a type-error
if row is not a row
.
(inverse !13427586) ⇒ !14236857 (inverse !14236857) ⇒ !13427586 (inverse !12436587) ⇒ !12436587 (inverse !12345678) ⇒ !12345678
Equivalent to (permute row (inverse change))
. Signals a
type-error
if either row or change is not a row
.
(permute-by-inverse !13456287 !45678123) ⇒ !28713456 (permute-by-inverse !54312 !2438756) ⇒ !54137862 (permute-by-inverse !762345 !4312) ⇒ !6271345
If there is a row
, r, of stage new-stage such that
(equalp (permute (rounds new-stage) r) row)
then returns r,
and otherwise nil
. That is, it returns a row of the new-stage such that the
first bells are as in row, and any new or omitted bells are in rounds order. If not
supplied new-stage defaults to the current value of *default-stage*
. Signals
a type-err
if row is not a row
or new-stage is not a
stage
.
(alter-stage !54321 10) ⇒ !5432167890 (alter-stage !5432167890 6) ⇒ !543216 (alter-stage !54321 4) ⇒ nil (alter-stage !5432167890 4) ⇒ nil
Previous: Rows, Up: Fundamental Types [Contents][Index]
Place notation is a succinct notation for writing sequences of changes, and is widely used
in change ringing. Roan provides functions for reading and writing place notation,
producing lists of row
s, representing changes.
Place notation manipulated by Roan is extended to support jump changes and comma as an unfolding operator for easy notation of palindromic sequences of changes.
Jump changes may be included in the place notation in two ways. Within changes may appear parenthesized pairs of places, indicating that the bell in the first place jumps to the second place. Thus the change (13)6 corresponds to the jump change 231546. As usual implied leading or lying places may be omitted, so that could also be written simply (13). However, just as with ordinary place notation, all internal places must be noted explicitly; for example, the change (13)(31) is illegal, and must be written (13)2(31). Using this notation the first half-lead of London Treble Jump Minor can be written 3x3.(24)x2x(35).4x4.3.
Jump changes may also be written by writing the full row between square brackets. So that same half-lead of London Treble Jump Minor could instead be notated 3x3[134265]x2x[214536]4x4.3. Or they can be mixed 3x3[134265]x2x(35).4x4.3.
Palindromes may be conveniently notated using a comma operator, which means the changes preceding the comma are rung backwads, following the last of the changes before the comma, which is not repeated; followed by the changes following the comma, similarly unfolded. Thus x3x4,2x3 is equivalent to x3x4x3x2x3x2. A piece of place notation may include at most one comma. Neither the changes before the comma nor after it may be empty. Any piece of place notation including a comma is necessarily of even length.
If jump changes appear in place notation that is being unfolded then when rung in reverse the jump changes are inverted; this makes no difference to ordinary changes, which are always involutions, but is important for jump changes that are not involutions. If the central change about which the unfolding operation takes place, that is the last change in a sequence of changes being unfolded, is not an involution an error is signaled. As an example, a plain lead of London Treble Jump Minor can be notated as 3x3.(24)x2x(35).4x4.3,2 which is equivalent to 3x3.(24)x2x(35).4x4.3.4x4.(53)x2x(42).3x3.2.
While place notation is normally written using dots (full stops) only between non-cross
changes, parse-place-notation
will accept, and ignore, them between any changes,
adjacent to other dots, and before and after place notation to be parsed. This may
simplify operation with other software that emits place notation with extraneous dots.
Just as Roan can augment the Lisp reader with ‘!’ to read row
s, it can augment
it with the ‘#!’ reader macro to read place notatation. The stage at which the place
notation is to be interpreted can be written as an integer between the ‘#’ and the
‘!’. If no explict stage is provided the current value (at read time) of
*default-stage*
is used. The sequence of place notation must be followed by a
character that cannot appear in place notation, such as whitespace, or by end of file.
There is an exception that an unbalanced close parenthesis will also end the reading; this
allows using this to read place notation in lists and vectors without requiring whitespace
following the place notation. The place notation may be extended with the comma unfolding
operator, and with jump changes. The stage at which the place notation is being iterpreted
is not considered in deciding which characters to consume; all that might apply as place
notation at any stage will be consumed. If some are not appropriate an error will only be
signaled after all the continguous, place notation characters have been read.
Note that, unlike row
s, which are Lisp atoms, the result of reading place notation
is a list, so ‘#!’ quotes it. This is appropriate in the usual case where the result
of ‘#!’ is evaluated, but if used in a context where it is not evaluated care must
be exercised.
This ‘#!’ syntax can be turned on and off by using roan-syntax. By default it is off when Roan is loaded. It is also possible to control this syntax by using Named Readtables; see roan-syntax for further details.
ROAN> #6!x2,1 (!214365 !124365 !214365 !132546) ROAN> '(symbol #6!x2,1 x #6!x2x1) (SYMBOL '(!214365 !124365 !214365 !132546) X '(!214365 !124365 !214365 !132546)) ROAN> `(symbol ,#6!x2,1 x ,#6!x2x1) (SYMBOL (!214365 !124365 !214365 !132546) X (!214365 !124365 !214365 !132546)) ROAN> #6!x2 (!214365 !124365) ROAN> (equalp #10!x1x4,2 #10!x1x4x1x2) T ROAN> #6!x3.(13)(64) (!214365 !213546 !231645) ROAN> #6!x3.(13).(64) (!214365 !213546 !231546 !132645) ROAN> #6!x3[231546](64) (!214365 !213546 !231546 !132645)
Parses place notation from string, returning a list of row
s, representing
changes, of stage stage. The place notation is parsed as applying to stage
stage, which, if not supplied, defaults to current value of *default-stage*
.
Only that portion of string between start and end is parsed; start
should be a non-negative integer, and end either an integer larger than start
or nil
, which latter is equivalent to the length of string. If
junk-allowed, a generalized Boolean, is nil
, the default, string must
consist of the place notation parsed and nothing else; otherwise non-place notation
characters may follow the place notation. For purposes of parsing stage is not
initially considered: if the place notation is only appropriate for higher stages it will
not terminate the parse even if junk-allowed is true, it will instead signal an
error. Two values are returned. The first is a list of row
s, the changes parsed.
The second is the index of the next character in string following the place notation
that was parsed.
If the section of string delimited by start and end does not contain
place notation suitable for stage a parse-error
is signaled. If
string is not a string, stage is not a stage
or start or
end are not suitable bounding index designators a type-error
is signaled.
(multiple-value-list (parse-place-notation "x2.3" :stage 6)) ⇒ ((!214365 !124365 !213546) 4)
Reads place notation from a stream, resulting in a list of row
s representing
changes. Reads all the consecutive characters that can appear in (extended) place
notation, and then tries to parse them as place notation. It accumulates characters that
could appear as place notation at any stage, even stages above stage. The sequence
of place notation must be followed by a character that cannot appear in place notation,
such as whitespace, or by end of file. There is an exception, in that an unbalanced close
parenthesis will also end the read; this allows using this to read place notation in lists
and vectors without requiring whitespace following the place notation. The place notation
may be extended with the comma unfolding operator, and with jump changes, as in
parse-place-notation
. The argument stream is a character stream open for
reading, and defaults to the current value of *standard-input*
; stage is a
stage
, an integer, and defaults to the current value of *default-stage*
; and
eof-error-p, eof-value and recursive-p are as for the standard
read
function, defaulting to t
, nil
and nil
, respectively.
Returns a non-empty list of row
s, all of stage stage. Signals an error if no
place notation constituents are available, if the characters read cannot be parsed
as (extended) place noation at stage, or if one of the usual errorneous conditions
while reading occurs.
Writes to stream characters representing place notation for changes, a list
of row
s.
The list changes should be a non-empty list of row
s, all of the same stage.
The stream should a character stream open for writing. It defaults to the current
value of *standard-output*
. If the generalized boolean escape, which defaults
to the current value of *print-escape*
, is true the place notation will be written
using the ‘#!’ read macro to allow the Lisp read
function to read it; in this
case the stage will always be explicitly noted between the ‘#’ and the ‘!’. If
the generalized boolean upper-case, which defaults to the current value of
*print-bells-upper-case*
, is true positions notated using letters will be written
in upper case, and otherwise in lower case.
The argument cross controls which character is used to denote a cross change at even
stages. It must be a character designator for #\x
, #\X
or #\-
,
and defaults to the current value of *cross-character*
.
The argument jump-changes should be one of nil
, :jumps
or :full
.
It determines how jump changes will be notated. If it is nil
and changes
contains any jump changes an error will be signaled. If it is :jumps
any jump
changes will be notated using pairs of places between parentheses. While
parse-place-notation
and read-place-notation
can interpret ordinary conjunct
motion or even place making notated in parentheses, write-place-notation
will only
use parentheses for bells actually moving more than one place. If jump-changes is
:full
jump changes will be notated as a row between square brackets. Again, while
ordinary changes notated this way can be parsed or read, write-place-notation
will
only use bracket notation for jump changes.
The argument elide determines whether, and how, to omit leading and/or lying places.
If the stage of the changes in changes is odd, or if elide is nil
, no
such elision takes place. Otherwise elide should be one of :interior
,
:leading
, :lying
or :lead-end
, which last is its default value. For
any of these non-nil values leading or lying places will always be elided if there are
interior places. They differ only for hunts (that is, changes with both a leading and
lying place, and no interior places). If :interior
, no elision takes place if there
are no interior places. If :leading
, the ’1’ is elided as implicitly available. If
:lying
, the lying place is elided, so that the result is always ’1’. The value
:lead-end
specifies the same behavior as :lying
for all the elements of
changes except the last, for which it behaves as :leading
; this is often
convenient for notating leads of treble dominated methods at even stages.
If the generalized boolean comma is true an attempt is made to write changes using a comma operator separating it into palindromes. In general there can be multiple ways of splitting an arbitrary piece of place notation into palindromes. If this is the case the choice is made to favor first a division that has the palindrome after the comma of length one, and if that is not possible the division that has the shortest palindrome before the comma. Any sequence of changes of length two can be trivially divided into palindromes, but notating them with a comma is unhelpful, so comma applies only to even length lists of changes of length greater than two. Whether or not a partitioning into palindromes was possible can be determined by examining the second value returned by this function, which will be true only if a comma was written.
Returns two values, changes, and a generalized Boolean indicating whether or not the result was written with a comma.
Signals an error if changes is empty, or contains rows of different stages, if stream is not a character stream open for writing, or if any of the usual IO errors occurs.
Returns a string of the place notation representing the list changes. The
arguments are the same as the like named arguments to write-place-notation
. A
leading ’#!’ is never included in the result.
Signals a type-error
if any elements of changes are not row
s. Signals
an error if changes is empty or contains rows of different stages.
(multiple-value-list (place-notation-string #8!x1x4,1 :elide nil)) ⇒ ("x18x14x18x18" nil) (multiple-value-list (place-notation-string #8!x1x4,1 :comma t)) ⇒ ("x1x4,8" t) (multiple-value-list (place-notation-string #8!x1x4,2 :elide :interior)) ⇒ ("x18x4x18x18" nil)
Returns a string representing the place notation in a canonical form. If
string-or-changes is a string it should be parseable as place notation at
stage, which defaults to the current value of *default-stage*
, and otherwise
it should be a list of row
s, all of the same stage. Unless overridden by the other
keyword arguments, which have the same effects as for write-place-notation
, the
canonical form is a compact one using lower case ‘x’ for cross, upper case letters for
high place names, lead-end
style elision of external places, a comma for unfolding
if possible, and notating jump changes as jumps within parentheses.
Signals a type-error
if string-or-changes is neither a string nor a list, or
if it is a list containing anything other than row
s. Signals a parse-error
if
string-or-changes is a string and is not parseable at stage, or if stage
is not a stage
. Signals an error if cross is not a suitable character
designator, if allow-jump-changes is not one of its allowed values, or if
string-or-changes is a list containing row
s of different stages.
See write-place-notation.
(multiple-value-list (canonicalize-place-notation "-16.X.14-6X1" :stage 6)) ⇒ ("x1x4,6" t) (multiple-value-list (canonicalize-place-notation "-3-[134265]-1T-" :stage 12)) ⇒ ("x3x(24)x1x" nil)
The character used by default as “cross” when writing place notation. Must be a
character designator for one of #\x
, #\X
or #\-
. Its initial
default value is a lower case ‘x’, #\x
.
Previous: Rows, Up: Fundamental Types [Contents][Index]