Several methods are implemented for the classes noteworthy
, noteinfo
,
music
and lyrics
. See further below for details on limited
implementations for the phrase
class.
In addition to custom print and summary methods, the following methods have
been implemented for all four classes: [
, [<-
, [[
, [[<-
, length()
,
c()
, rep()
, rev()
, head()
and tail()
. Logical operators are also
implemented for noteworthy strings.
length()
and c()
The implementation of length()
is equivalent to n_steps()
. They
access the same attribute, returning the number of timesteps in the object.
This gives the same result even when the underlying string is in
space-delimited format. To obtain the character string length, coerce with
as.character()
or any other function that would have the same effect.
The implementation of c()
for these classes is strict and favors the
object class in question. This is different from how c()
might normally
behave, coercing objects of different types such as numeric and character to
character.
For these four classes, c()
is strict in that it will return
an error if attempting to concatenate one of these classes with any other
class besides character. This includes each other. While it would be
possible to coerce a music object down to a noteworthy
object or a
noteinfo
object, this is the opposite of the aggressive coercion
these classes are intended to have with c()
so this is not done.
While other classes such as numeric immediately return an error, any
concatenation with character strings attempts to coerce each character
string present to the given class. If coercion fails for any character class
object, the usual error is returned concerning invalid notes or note info
present. If coercion succeeds for all character strings, the result of
c()
is to concatenate the timesteps of all objects passed to it. The
output is a new noteworthy
, noteinfo
ormusic
object.
rep()
rev()
head()
and tail()
The rep()
function is similar to c()
except that it never has to consider
other classes. You could pass a vector of objects to rep()
, but doing so
with c()
will already have resolved all objects to the single class. Again,
what matters is not the underlying length or elements in the character vector
the class is built upon, but the timesteps. rep()
will extend x
in terms
of timesteps. You can also provide the each
or times
arguments.
rev()
, head()
and tail()
work similarly, based on the sequence of
timesteps, not the character vector length.
Remember that this accounts not only for vectors of length one that contain
multiple timesteps in space-delimited time format, but also that multiple
timesteps can be condensed even in space-delimited time format with the
*
expansion operator.
For example, "a'*4 b'*2"
has six timesteps in this form as well as in
vector form. The object length is neither one nor two. All of these generic
method implementations work in this manner.
Single and double bracket subsetting by index work similarly to what occurs with lists. Single bracket subsetting returns the same object, but only containing the indexed timesteps. Double bracket subsetting only operates on a single timestep and extracts the character string value.
For assignment, single and double brackets change the value at timesteps and return the same object, but again double brackets only allow indexing a single timestep. Double bracket indexing is mostly useful for combining the steps of extracting a single value and discarding the special class in one command.
Methods implemented for the phrase
class are limited to c()
and rep()
.
Due to the complex LilyPond syntax, applying most of the functions above
directly to phrases is problematic. c()
is implemented like it is for the
other classes. rep()
is restricted in that it can only repeat the entire
phrase sequence, not the timesteps within. However, you can convert a phrase
class back to noteworthy
and noteinfo
objects (under reasonable
conditions). See notify()
.
One exception made for phrase
objects with respect to concatenation is that
an attempt to concatenate any combination of phrase and music objects, in
any order, results in coercion to a new phrase. This happens even in a case
where the first object in the sequence is a music object (thus calling
c.music()
rather than c.phrase()
). It will subsequently fall back
to c.phrase()
in that case.
# noteworthy class examples
x <- as_noteworthy("a, b, c ce_g d4f#4a4")
x
#> <Noteworthy string>
#> Format: space-delimited time
#> Values: a, b, c <ce_g> <d'g_'a'>
x[3:4]
#> <Noteworthy string>
#> Format: space-delimited time
#> Values: c <ce_g>
x[-2]
#> <Noteworthy string>
#> Format: space-delimited time
#> Values: a, c <ce_g> <d'g_'a'>
x[2] <- paste0(transpose(x[2], 1), "~")
x
#> <Noteworthy string>
#> Format: space-delimited time
#> Values: a, c~ c <ce_g> <d'g_'a'>
length(x) # equal to number of timesteps
#> [1] 5
c(x, x)
#> <Noteworthy string>
#> Format: space-delimited time
#> Values: a, c~ c <ce_g> <d'g_'a'> a, c~ c <ce_g> <d'g_'a'>
tail(rep(x, times = c(1, 2, 1, 3, 1)))
#> <Noteworthy string>
#> Format: space-delimited time
#> Values: c~ c <ce_g> <ce_g> <ce_g> <d'g_'a'>
# noteinfo class examples
x <- as_noteinfo(c("4-", "t8(", "t8)", "t8x", "8^", "16"))
x
#> <Note info string>
#> Format: vectorized time
#> Values: 4- t8( t8) t8x 8^ 16
x[2:4]
#> <Note info string>
#> Format: vectorized time
#> Values: t8( t8) t8x
x[-1]
#> <Note info string>
#> Format: vectorized time
#> Values: t8( t8) t8x 8^ 16
x[5:6] <- c("16^", "8")
x
#> <Note info string>
#> Format: vectorized time
#> Values: 4- t8( t8) t8x 16^ 8
x[x == "4-"]
#> <Note info string>
#> Format: vectorized time
#> Values: 4-
c(x[1], x[2]) == c(x[1:2])
#> [1] TRUE TRUE
head(rep(x, each = 2))
#> <Note info string>
#> Format: vectorized time
#> Values: 4- 4- t8( t8( t8) t8)
# music class examples
x <- as_music("c,~4 c,1 c'e_'g'4-.*4")
x
#> <Music string>
#> Format: space-delimited time
#> Values: c,~4 c,1 <c'e_'g'>4-. <c'e_'g'>4-. <c'e_'g'>4-. <c'e_'g'>4-.
x[1:3]
#> <Music string>
#> Format: space-delimited time
#> Values: c,~4 c,1 <c'e_'g'>4-.
x[-c(1:2)]
#> <Music string>
#> Format: space-delimited time
#> Values: <c'e_'g'>4-. <c'e_'g'>4-. <c'e_'g'>4-. <c'e_'g'>4-.
x[3:6] <- "c'e'g'8"
x
#> <Music string>
#> Format: space-delimited time
#> Values: c,~4 c,1 <c'e'g'>8 <c'e'g'>8 <c'e'g'>8 <c'e'g'>8
c(x[1], x[1]) == x[c(1, 1)]
#> [1] TRUE
rev(x)
#> <Music string>
#> Format: space-delimited time
#> Values: <c'e'g'>8 <c'e'g'>8 <c'e'g'>8 <c'e'g'>8 c,1 c,~4
x[[3]]
#> [1] "c'e'g'8"
x[[3]] <- "b_t8"
x
#> <Music string>
#> Format: space-delimited time
#> Values: c,~4 c,1 b_t8 <c'e'g'>8 <c'e'g'>8 <c'e'g'>8