]> git.donarmstrong.com Git - lilypond.git/blobdiff - Documentation/es/extending/scheme-tutorial.itely
Doc-es: update Scheme tutorial.
[lilypond.git] / Documentation / es / extending / scheme-tutorial.itely
index 42642987f9ee125291c2a0758799b78a4e371f32..a08ac6ef31507dc87dd5220b6ac491019dad68d1 100644 (file)
@@ -1,20 +1,19 @@
 @c -*- coding: utf-8; mode: texinfo; documentlanguage: es -*-
 
 @ignore
 @c -*- coding: utf-8; mode: texinfo; documentlanguage: es -*-
 
 @ignore
-    Translation of GIT committish: 10bd5cc93870ac4b884b8cb938cfc6a19c768097
+    Translation of GIT committish: 1f0a00b69403290b7fc7527b9ab100f95533f954
 
     When revising a translation, copy the HEAD committish of the
     version that you are working on.  For details, see the Contributors'
     Guide, node Updating translation committishes..
 @end ignore
 
 
     When revising a translation, copy the HEAD committish of the
     version that you are working on.  For details, see the Contributors'
     Guide, node Updating translation committishes..
 @end ignore
 
-@c \version "2.13.36"
+@c \version "2.15.20"
 
 @node Tutorial de Scheme
 @appendix Tutorial de Scheme
 @translationof Scheme tutorial
 
 
 @node Tutorial de Scheme
 @appendix Tutorial de Scheme
 @translationof Scheme tutorial
 
-@funindex #
 @cindex Scheme
 @cindex GUILE
 @cindex Scheme, código en línea
 @cindex Scheme
 @cindex GUILE
 @cindex Scheme, código en línea
@@ -80,7 +79,15 @@ LilyPond (para conocer la ruta completa a esta carpeta, consulte
 usuarios de Windows pueden seleccionar simplemente @q{Ejecutar} del
 menú Inicio e introducir @q{guile}.
 
 usuarios de Windows pueden seleccionar simplemente @q{Ejecutar} del
 menú Inicio e introducir @q{guile}.
 
-Una vez está funcionando el cajón de arena de Guile, verá un indicador
+Sin embargo, está disponible un cajón de arena de Scheme listo para
+funcionar con todo LilyPond cargado, con esta instrucción de la línea
+de órdenes:
+@example
+lilypond scheme-sandbox
+@end example
+
+@noindent
+Una vez está funcionando el cajón de arena, verá un indicador
 del sistema de Guile:
 
 @lisp
 del sistema de Guile:
 
 @lisp
@@ -161,7 +168,7 @@ Los valores Booleanos son Verdadero y Falso.  Verdadero en Scheme es
 
 @item Números
 Los números se escriben de la forma normal, @code{1} es el número
 
 @item Números
 Los números se escriben de la forma normal, @code{1} es el número
-(entero) uno, mientras que @code{-1.5} es un número en coma flotante
+(entero) uno, mientras que @w{@code{-1.5}} es un número en coma flotante
 (un número no entero).
 
 @item Cadenas
 (un número no entero).
 
 @item Cadenas
@@ -639,30 +646,80 @@ guile> (cond ((< a b) "a es menor que b")
 @node Sintaxis del Scheme de LilyPond
 @subsection Sintaxis del Scheme de LilyPond
 @translationof LilyPond Scheme syntax
 @node Sintaxis del Scheme de LilyPond
 @subsection Sintaxis del Scheme de LilyPond
 @translationof LilyPond Scheme syntax
+@funindex $
+@funindex #
 
 El intérprete Guile forma parte de LilyPond, lo que significa que se
 puede incluir Scheme dentro de los archivos de entrada de LilyPond.
 
 El intérprete Guile forma parte de LilyPond, lo que significa que se
 puede incluir Scheme dentro de los archivos de entrada de LilyPond.
-La marca de almohadilla @code{#} se utiliza para indicar al analizador
-sintáctico de LilyPond que lo siguiente es un valor de Scheme.
-
-Una vez el analizador sintáctico se encuentra con un símbolo de
-almohadilla, la entrada se le pasa al intérprete Guile para evaluar la
-expresión de Scheme.  El intérprete continúa procesando la entrada
-hasta que se encuentra con el final de una expresión de Scheme.
-
-Los procedimientos de Scheme se pueden definir dentro de los archivos
-de entrada de LilyPond:
+Existen varios métodos para incluir Scheme dentro de LilyPond.
+
+La manera más sencilla es utilizar el símbolo de
+almohadilla@tie{}@code{#} antes de una expresión de Scheme.
+
+Ahora bien, el código de entrada de LilyPond se estructura en
+elementos y expresiones, de forma parecida a cómo el lenguaje humano
+se estructura en palabras y frases.  LilyPond tiene un analizador
+léxico que reconoce elementos indivisibles (números literales, cadenas
+de texto, elementos de Scheme, nombres de nota, etc.), y un analizador
+sintáctico que entiende la sintaxis, la @ruser{Gramática de LilyPond}.
+Una vez que sabe que se aplica una regla sintáctica concreta, ejecuta
+las acciones asociadas con ella.
+
+El método del símbolo de almohadilla@tie{}@code{#} para incrustar
+Scheme se adapta de forma natural a este sistema.  Una vez que el
+analizador léxico ve un símbolo de almohadilla, llama al lector de
+Scheme para que lea una expresión de Scheme completa (que puede ser un
+identificador, una expresión encerrada entre paréntesis, o algunas
+otras cosas).  Después de que se ha leído la expresión de Scheme, se
+almacena como el valor de un elemento @code{SCM_TOKEN} de la
+gramática.  Después de que el analizador sintáctico ya sabe cómo hacer
+uso de este elemento, llama a Guila para que evalúe la expresión de
+Scheme.  Dado que el analizador sintáctico suele requerir un poco de
+lectura por delante por parte del analizador léxico para tomar sus
+decisiones de análisis sintáctico, esta separación de lectura y
+evaluación entre los analizadores léxico y sintáctico es justamente lo
+que se necesita para mantener sincronizadas las ejecuciones de
+expresiones de LilyPond y de Scheme.  Por este motivo se debe usar el
+símbolo de almohadilla@tie{}@code{#} para llamar a Scheme siempre que
+sea posible.
+
+Otra forma de llamar al intérprete de Scheme desde lilyPond es el uso
+del símbolo de dólar@tie{}@code{$} en lugar de la almohadilla para
+introducir las expresiondes de Scheme.  En este caso, LilyPond evalúa
+el código justo después de que el analizador léxico lo ha leído.
+Comprueba el tipo resultante de la expresión de Scheme y después
+selecciona un tipo de elemento (uno de los varios elementos
+@code{xxx_IDENTIFIER} dentro de la sintaxis) para él.  Crea una
+@emph{copia} del valor y la usa como valor del elemento.  Si el valor
+de la expresión es vacío (El valor de Guile de @code{*unspecified*}),
+no se pasa nada en absoluto al analizador sintáctico.
+
+Éste es, de hecho, el mismo mecanismo exactamente que LilyPond emplea
+cuando llamamos a cualquier variable o función musical por su nombre,
+como @code{\nombre}, con la única diferencia de que su final viene
+determinado por el analizador léxico de LilyPond sin consultar al
+lector de Scheme, y así solamente se aceptan los nombres de variable
+consistentes con el modo actual de LilyPond.
+
+La acción inmediata de @code{$} puede llevar a alguna que otra
+sorpresa, véase @ref{Variables de entrada y Scheme}.  La utilización
+de @code{#} donde el analizador sintáctico lo contempla es normalmente
+preferible.
+
+Ahora echemos un vistazo a algo de código de Scheme real.  Los
+procedimientos de Scheme se pueden definir dentro de los archivos de
+entrada de LilyPond:
 
 @example
 
 @example
-#(define (average a b c) (/ (+ a b c) 3))
+#(define (media a b c) (/ (+ a b c) 3))
 @end example
 
 Observe que los comentarios de LilyPond (@code{%} y @code{%@{ %@}}) no
 se pueden utilizar dentro del código de Scheme, ni siquiera dentro de
 @end example
 
 Observe que los comentarios de LilyPond (@code{%} y @code{%@{ %@}}) no
 se pueden utilizar dentro del código de Scheme, ni siquiera dentro de
-un archivo de entrada de LilyPond input file, porque es el intérprete
-Guile, y no el analizador sintáctico de LilyPond, el que está
-interpretando la expresión de Scheme.  Los comentarios en el Scheme de
-Guile se introducen como sigue:
+un archivo de entrada de LilyPond, porque es el intérprete Guile, y no
+el analizador léxico de LilyPond, el que está leyendo la expresión de
+Scheme.  Los comentarios en el Scheme de Guile se introducen como
+sigue:
 
 @example
 ; esto es un comentario de una línea
 
 @example
 ; esto es un comentario de una línea
@@ -675,8 +732,8 @@ Guile se introducen como sigue:
 @end example
 
 Durante el resto de esta sección, supondremos que los datos se
 @end example
 
 Durante el resto de esta sección, supondremos que los datos se
-introducen en un archivo de música, por lo que añadiremos almohadillas
-@code{#} al principio de todas las expresiones de Scheme.
+introducen en un archivo de música, por lo que añadiremos
+almohadillas@tie{}@code{#} al principio de todas las expresiones de Scheme.
 
 Todas las expresiones de Scheme del nivel jerárquico superior dentro
 de un archivo de entrada de LilyPond se pueden combinar en una sola
 
 Todas las expresiones de Scheme del nivel jerárquico superior dentro
 de un archivo de entrada de LilyPond se pueden combinar en una sola
@@ -718,6 +775,18 @@ veintiCuatro = (* 2 doce)
 lo que daría lugar a que el número 24 se almacenase dentro de la
 variable @code{veintiCuatro} de LilyPond (y de Scheme).
 
 lo que daría lugar a que el número 24 se almacenase dentro de la
 variable @code{veintiCuatro} de LilyPond (y de Scheme).
 
+La forma usual de referirse a las variables de LilyPond,
+@ref{Sintaxis del Scheme de LilyPond},
+
+es llamarlas usando una barra invertida, es decir
+@code{\veintiCuatro}.  Dado que esto crea una copia para la mayor
+parte de los tipos internos de LilyPond, concretamente las expresiones
+musicales, las funciones musicales no sueln crear copias del material
+que ellas mismas modifican.  Por este motivo, las expresiones
+musicales dadas con @code{#} no deberían, por lo general, contener
+material que no se haya creado partiendo de cero o copiado
+explícitamente en lugar de estar referenciado directamente.
+
 @node Variables de entrada y Scheme
 @subsection Variables de entrada y Scheme
 @translationof Input variables and Scheme
 @node Variables de entrada y Scheme
 @subsection Variables de entrada y Scheme
 @translationof Input variables and Scheme
@@ -770,9 +839,6 @@ usando Scheme.  El resultado se importa dentro de un bloque
 @lilypond[verbatim]
 traLaLa = { c'4 d'4 }
 
 @lilypond[verbatim]
 traLaLa = { c'4 d'4 }
 
-%% dummy action to deal with parser lookahead
-#(display "this needs to be here, sorry!")
-
 #(define newLa (map ly:music-deep-copy
   (list traLaLa traLaLa)))
 #(define twice
 #(define newLa (map ly:music-deep-copy
   (list traLaLa traLaLa)))
 #(define twice
@@ -783,27 +849,44 @@ traLaLa = { c'4 d'4 }
 
 @c Due to parser lookahead
 
 
 @c Due to parser lookahead
 
-En este ejemplo, la asignación se produce después de que el analizador
-sintáctico ha verificado que no ocurre nada interesante después de
-@code{traLaLa = @{ ... @}}.  Sin la sentencia muda del ejemplo
-anterior, la definición de @code{newLa} se ejecuta antes de que se
-defina @code{traLaLa}, produciendo un error de sintaxis.
+En realidad, éste es un ejemplo bastante interesante.  La asignación
+solo tiene lugar después de que el analizador sintáctico se ha
+asegurado de que no sigue nada parecido a @code{\addlyrics}, de manera
+que necesita comprobar lo que viene a continuación.  Lee el símbolo
+@code{#} y la expresión de Scheme siguiente @emph{sin} evaluarla, de
+forma que puede proceder a la asignación, y @emph{posteriormente}
+ejecutar el código de Scheme sin problema.
 
 El ejemplo anterior muestra cómo @q{exportar} expresiones musicales
 desde la entrada al intérprete de Scheme.  Lo contrario también es
 
 El ejemplo anterior muestra cómo @q{exportar} expresiones musicales
 desde la entrada al intérprete de Scheme.  Lo contrario también es
-posible.  Envolviendo un valor de Scheme en la función
-@code{ly:export}, se interpreta un valor de Scheme como si hubiera
-sido introducido en la sintaxis de LilyPond.  En lugar de definir
-@code{\twice}, el ejemplo anterior podría también haberse escrito como
+posible.  Colocándolo después de @code{$}, un valor de Scheme se
+interpreta como si hubiera sido introducido en la sintaxis de
+LilyPond.  En lugar de definir @code{\twice}, el ejemplo anterior
+podría también haberse escrito como
 
 @example
 ...
 
 @example
 ...
-@{ #(ly:export (make-sequential-music (list newLa))) @}
+@{ $(make-sequential-music (list newLa)) @}
 @end example
 
 @end example
 
-El código de Scheme se evalúa tan pronto como el analizador sintáctico
-lo encuentra.  Para definir código de Scheme dentro de un macro (para
-llamarse más tarde), utilice @ref{Funciones vacías}, o bien
+Podemos utilizar @code{$} con una expresión de Scheme en cualquier
+lugar en el que usaríamos @code{\@var{nombre}} después de haber
+asignado la expresión de Scheme a una variable @var{nombre}.  Esta
+sustitución se produce dentro del @q{analizador léxico}, de manera que
+LilyPond no llega a darse cuenta de la diferencia.
+
+Sin embargo, existe un inconveniente, el de la medida del tiempo.  Si
+hubiésemos estado usando @code{$} en vez de @code{#} para definir
+@code{newLa} en el ejemplo anterior, la siguiente definición de Scheme
+habría fracasado porque @code{traLaLa} no habría sido definida aún.
+Para ver una explicación de este problema de momento temporal, véase
+@ref{Sintaxis del Scheme de LilyPond}.
+
+En cualquier caso, la evaluación del código de Scheme se produce
+dentro del analizador sintáctico como muy tarde.  Si necesitamos que
+se ejecute en un punto temporal más tardío,
+usaríamos @ref{Funciones de Scheme vacías}, o lo almacenaríamos en un
+macro:
 
 @example
 #(define (nopc)
 
 @example
 #(define (nopc)
@@ -817,7 +900,7 @@ llamarse más tarde), utilice @ref{Funciones vacías}, o bien
 @knownissues
 
 No es posible mezclar variables de Scheme y de LilyPond con la opción
 @knownissues
 
 No es posible mezclar variables de Scheme y de LilyPond con la opción
-@code{--safe}.
+@option{--safe}.
 
 
 @node Propiedades de los objetos
 
 
 @node Propiedades de los objetos
@@ -864,7 +947,7 @@ tiene una propiedad @code{thickness} (grosor), mientras que
 @subheading Desplazamientos
 
 Los desplazamientos bidimensionales (coordenadas X e Y) se almacenan
 @subheading Desplazamientos
 
 Los desplazamientos bidimensionales (coordenadas X e Y) se almacenan
-como @code{parejas}.  El @code{car} del desplazamiento es la
+como @emph{parejas}.  El @code{car} del desplazamiento es la
 coordenada X, y el @code{cdr} es la coordenada Y.
 
 @example
 coordenada X, y el @code{cdr} es la coordenada Y.
 
 @example
@@ -879,6 +962,16 @@ espacio de pentagrama a la derecha, y dos espacios hacia arriba.
 Los procedimientos para trabajar con desplazamientos están en
 @file{scm/lily-library.scm}.
 
 Los procedimientos para trabajar con desplazamientos están en
 @file{scm/lily-library.scm}.
 
+@subheading Fractions
+
+Fractions as used by LilyPond are again stored as @emph{pairs}, this
+time of unsigned integers.  While Scheme can represent rational numbers
+as a native type, musically @samp{2/4} and @samp{1/2} are not the same,
+and we need to be able to distinguish between them.  Similarly there are
+no negative @q{fractions} in LilyPond's mind.  So @code{2/4} in LilyPond
+means @code{(2 . 4)} in Scheme, and @code{#2/4} in LilyPond means
+@code{1/2} in Scheme.
+
 @subheading Dimensiones
 
 Las parejas se usan también para almacenar intervalos, que representan
 @subheading Dimensiones
 
 Las parejas se usan también para almacenar intervalos, que representan
@@ -1019,18 +1112,16 @@ imprime lo siguiente:
   'SequentialMusic
   'elements
   (list (make-music
   'SequentialMusic
   'elements
   (list (make-music
-          'EventChord
-          'elements
+          'NoteEvent
+          'articulations
           (list (make-music
           (list (make-music
-                  'NoteEvent
-                  'duration
-                  (ly:make-duration 2 0 1 1)
-                  'pitch
-                  (ly:make-pitch 0 0 0))
-                (make-music
                   'AbsoluteDynamicEvent
                   'text
                   'AbsoluteDynamicEvent
                   'text
-                  "f")))))
+                  "f"))
+          'duration
+          (ly:make-duration 2 0 1 1)
+          'pitch
+          (ly:make-pitch 0 0 0))))
 @end example
 
 De forma predeterminada, LilyPond imprime estos mensajes sobre la
 @end example
 
 De forma predeterminada, LilyPond imprime estos mensajes sobre la
@@ -1042,27 +1133,45 @@ salida a un archivo.
 lilypond archivo.ly >salida.txt
 @end example
 
 lilypond archivo.ly >salida.txt
 @end example
 
-Con la aplicación de un poco de formateo, la información anterior es
-fácil de leer,
+Con un poco de magia combinada de LilyPond y Scheme, podemos realmente
+hacer que LilyPond dirija solamente esta salida a su propio archivo:
+
+@example
+@{
+  $(with-output-to-file "display.txt"
+      (lambda () #@{ \displayMusic @{ c'4\f @} #@}))
+@}
+@end example
+
+
+Un poco de reformateo hace a la información anterior más fácil de
+leer:
 
 @example
 (make-music 'SequentialMusic
 
 @example
 (make-music 'SequentialMusic
-  'elements (list (make-music 'EventChord
-                    'elements (list (make-music 'NoteEvent
-                                      'duration (ly:make-duration 2 0 1 1)
-                                      'pitch (ly:make-pitch 0 0 0))
-                                    (make-music 'AbsoluteDynamicEvent
-                                      'text "f")))))
+  'elements (list
+            (make-music 'NoteEvent
+               'articulations (list
+                              (make-music 'AbsoluteDynamicEvent
+                                'text
+                                "f"))
+              'duration (ly:make-duration 2 0 1 1)
+              'pitch    (ly:make-pitch 0 0 0))))
 @end example
 
 Una secuencia musical @code{@{ ... @}} tiene el nombre
 @code{SequentialMusic}, y sus expresiones internas se almacenan coma
 una lista dentro de su propiedad @code{'elements}.  Una nota se
 @end example
 
 Una secuencia musical @code{@{ ... @}} tiene el nombre
 @code{SequentialMusic}, y sus expresiones internas se almacenan coma
 una lista dentro de su propiedad @code{'elements}.  Una nota se
-representa como una expresión @code{EventChord} que contiene un objeto
-@code{NoteEvent} (que almacena las propiedades de duración y altura) y
-cualquier información adicional (en este caso, un evento
-@code{AbsoluteDynamicEvent} con una propiedad @code{"f"} de texto.
+representa como un objeto @code{NoteEvent} (que almacena las
+propiedades de duración y altura) con información adjunta (en este
+caso, un evento @code{AbsoluteDynamicEvent} con una propiedad
+@code{"f"} de texto) almacenada en su propiedad @code{articulations}.
 
 
+@funindex{\void}
+@code{\displayMusic} devuelve la música que imprime en la consola, y
+por ello se interpretará al tiempo que se imprime en la consola.  Para
+evitar la interpretación, escriba @code{\void} antes de
+@code{\displayMusic}.
 
 @node Propiedades musicales
 @subsection Propiedades musicales
 
 @node Propiedades musicales
 @subsection Propiedades musicales
@@ -1072,13 +1181,27 @@ cualquier información adicional (en este caso, un evento
 @c @emph{context} properties, and @emph{layout} properties.  These
 @c are potentially confusing.
 
 @c @emph{context} properties, and @emph{layout} properties.  These
 @c are potentially confusing.
 
-El objeto @code{NoteEvent} es el primer objeto de la propiedad
-@code{'elements} de @code{someNote}.
+Veamos un ejemplo:
 
 @example
 someNote = c'
 \displayMusic \someNote
 ===>
 
 @example
 someNote = c'
 \displayMusic \someNote
 ===>
+(make-music
+  'NoteEvent
+  'duration
+  (ly:make-duration 2 0 1 1)
+  'pitch
+  (ly:make-pitch 0 0 0))
+@end example
+
+The @code{NoteEvent} object is the representation of @code{someNote}.
+Straightforward.  How about putting c' in a chord?
+
+@example
+someNote = <c'>
+\displayMusic \someNote
+===>
 (make-music
   'EventChord
   'elements
 (make-music
   'EventChord
   'elements
@@ -1090,6 +1213,9 @@ someNote = c'
           (ly:make-pitch 0 0 0))))
 @end example
 
           (ly:make-pitch 0 0 0))))
 @end example
 
+Ahora el objeto @code{NoteEvent} es el primer objeto
+de la propiedad @code{'elements} de @code{someNote}.
+
 La función @code{display-scheme-music} es la función que se usa por
 parte de @code{\displayMusic} para imprimir la representación de
 Scheme de una expresión musical.
 La función @code{display-scheme-music} es la función que se usa por
 parte de @code{\displayMusic} para imprimir la representación de
 Scheme de una expresión musical.
@@ -1136,7 +1262,7 @@ d'
 @translationof Doubling a note with slurs (example)
 
 Supongamos que queremos crear una función que convierte una entrada
 @translationof Doubling a note with slurs (example)
 
 Supongamos que queremos crear una función que convierte una entrada
-como @code{a} en @code{a( a)}.  Comenzamos examinando la
+como @code{a} en @code{@{ a( a) @}}.  Comenzamos examinando la
 representación interna de la música con la que queremos terminar.
 
 @example
 representación interna de la música con la que queremos terminar.
 
 @example
@@ -1146,71 +1272,68 @@ representación interna de la música con la que queremos terminar.
   'SequentialMusic
   'elements
   (list (make-music
   'SequentialMusic
   'elements
   (list (make-music
-          'EventChord
-          'elements
+          'NoteEvent
+          'articulations
           (list (make-music
           (list (make-music
-                  'NoteEvent
-                  'duration
-                  (ly:make-duration 2 0 1 1)
-                  'pitch
-                  (ly:make-pitch 0 5 0))
-                (make-music
                   'SlurEvent
                   'span-direction
                   'SlurEvent
                   'span-direction
-                  -1)))
+                  -1))
+          'duration
+          (ly:make-duration 2 0 1 1)
+          'pitch
+          (ly:make-pitch 0 5 0))
         (make-music
         (make-music
-          'EventChord
-          'elements
+          'NoteEvent
+          'articulations
           (list (make-music
           (list (make-music
-                  'NoteEvent
-                  'duration
-                  (ly:make-duration 2 0 1 1)
-                  'pitch
-                  (ly:make-pitch 0 5 0))
-                (make-music
                   'SlurEvent
                   'span-direction
                   'SlurEvent
                   'span-direction
-                  1)))))
+                  1))
+          'duration
+          (ly:make-duration 2 0 1 1)
+          'pitch
+          (ly:make-pitch 0 5 0))))
 @end example
 
 @end example
 
-Las malas noticias son que las expresiones @code{SlurEvent} se deben
-añadir @q{dentro} de la nota (o para ser más exactos, dentro de la
-expresión @code{EventChord}).
+La mala noticia es que las expresiones @code{SlurEvent} se deben
+añadir @q{dentro} de la nota (dentro de la
+propiedad @code{articulations}).
 
 Ahora examinamos la entrada,
 
 @example
 
 Ahora examinamos la entrada,
 
 @example
+\displayMusic a'
+===>
 (make-music
 (make-music
-  'SequentialMusic
-  'elements
-  (list (make-music
-          'EventChord
-          'elements
-          (list (make-music
-                  'NoteEvent
-                  'duration
-                  (ly:make-duration 2 0 1 1)
-                  'pitch
-                  (ly:make-pitch 0 5 0))))))
+  'NoteEvent
+  'duration
+  (ly:make-duration 2 0 1 1)
+  'pitch
+  (ly:make-pitch 0 5 0))))
 @end example
 
 Así pues, en nuestra función, tenemos que clonar esta expresión (de
 forma que tengamos dos notas para construir la secuencia), añadir
 @end example
 
 Así pues, en nuestra función, tenemos que clonar esta expresión (de
 forma que tengamos dos notas para construir la secuencia), añadir
-@code{SlurEvent} a la propiedad @code{'elements} de cada una de
+@code{SlurEvent} a la propiedad @code{'articulations} de cada una de
 ellas, y por último hacer una secuencia @code{SequentialMusic} con los
 ellas, y por último hacer una secuencia @code{SequentialMusic} con los
-dos @code{EventChords}.
+dos @code{EventChords}.  Para añadir a una propiedad, es útil saber
+que una propiedad no establecida se lee como @code{'()}, la lista
+vacía, así que no se requiere ninguna comprobación especial antes de
+que pongamos otro elemento delante de la propiedad
+@code{articulations}.
+
 
 @example
 doubleSlur = #(define-music-function (parser location note) (ly:music?)
          "Return: @{ note ( note ) @}.
 
 @example
 doubleSlur = #(define-music-function (parser location note) (ly:music?)
          "Return: @{ note ( note ) @}.
-         `note' is supposed to be an EventChord."
+         `note' is supposed to be a single note."
          (let ((note2 (ly:music-deep-copy note)))
          (let ((note2 (ly:music-deep-copy note)))
-           (set! (ly:music-property note 'elements)
+           (set! (ly:music-property note 'articulations)
                  (cons (make-music 'SlurEvent 'span-direction -1)
                  (cons (make-music 'SlurEvent 'span-direction -1)
-                       (ly:music-property note 'elements)))
-           (set! (ly:music-property note2 'elements)
+                       (ly:music-property note 'articulations)))
+           (set! (ly:music-property note2 'articulations)
                  (cons (make-music 'SlurEvent 'span-direction 1)
                  (cons (make-music 'SlurEvent 'span-direction 1)
-                       (ly:music-property note2 'elements)))
+                       (ly:music-property note2 'articulations)))
            (make-music 'SequentialMusic 'elements (list note note2))))
 @end example
 
            (make-music 'SequentialMusic 'elements (list note note2))))
 @end example
 
@@ -1222,7 +1345,11 @@ doubleSlur = #(define-music-function (parser location note) (ly:music?)
 La manera fácil de añadir articulación a las notas es mezclar dos
 expresiones musicales en un solo contexto, como se explica en
 @ruser{Crear contextos}.  Sin embargo, supongamos que queremos
 La manera fácil de añadir articulación a las notas es mezclar dos
 expresiones musicales en un solo contexto, como se explica en
 @ruser{Crear contextos}.  Sin embargo, supongamos que queremos
-escribir una función musical que lo haga.
+escribir una función musical que lo haga.  Esto tiene la ventaja
+adicional de que podemos usar esa función musical para añadir una
+articulación (como una instrucción de digitación) a una nota única
+dentro de un acorde, lo cual no es posible si nos limitamos a mezclar
+fragmentos de música independientes.
 
 Una @code{$variable} dentro de la notación @code{#@{...#@}} es como
 una @code{\variable} normal en la notación clásica de LilyPond.
 
 Una @code{$variable} dentro de la notación @code{#@{...#@}} es como
 una @code{\variable} normal en la notación clásica de LilyPond.
@@ -1249,61 +1376,54 @@ Scheme.  Empezamos examinando nuestra entrada y la salida deseada,
 \displayMusic c4
 ===>
 (make-music
 \displayMusic c4
 ===>
 (make-music
-  'EventChord
-  'elements
-  (list (make-music
-          'NoteEvent
-          'duration
-          (ly:make-duration 2 0 1 1)
-          'pitch
-          (ly:make-pitch -1 0 0))))
+  'NoteEvent
+  'duration
+  (ly:make-duration 2 0 1 1)
+  'pitch
+  (ly:make-pitch -1 0 0))))
 =====
 %  desired output
 \displayMusic c4->
 ===>
 (make-music
 =====
 %  desired output
 \displayMusic c4->
 ===>
 (make-music
-  'EventChord
-  'elements
+  'NoteEvent
+  'articulations
   (list (make-music
   (list (make-music
-          'NoteEvent
-          'duration
-          (ly:make-duration 2 0 1 1)
-          'pitch
-          (ly:make-pitch -1 0 0))
-        (make-music
           'ArticulationEvent
           'articulation-type
           'ArticulationEvent
           'articulation-type
-          "marcato")))
+          "accent"))
+  'duration
+  (ly:make-duration 2 0 1 1)
+  'pitch
+  (ly:make-pitch -1 0 0))
 @end example
 
 Vemos que una nota (@code{c4}) se representa como una expresión
 @end example
 
 Vemos que una nota (@code{c4}) se representa como una expresión
-@code{EventChord}, con una expresión @code{NoteEvent} en su lista de
-elementos.  Para añadir una articulación de marcato, se debe añadir
-una expresión @code{ArticulationEvent} a la propiedad elements de la
-expresión @code{EventChord}.
+@code{NoteEvent}.  Para añadir una articulación de acento, se debe
+añadir una expresión @code{ArticulationEvent} a la propiedad
+@code{articulations} de la expresión @code{NoteEvent}.
 
 Para construir esta función, empezamos con
 
 @example
 
 Para construir esta función, empezamos con
 
 @example
-(define (add-marcato event-chord)
-  "Add a marcato ArticulationEvent to the elements of `event-chord',
-  which is supposed to be an EventChord expression."
-  (let ((result-event-chord (ly:music-deep-copy event-chord)))
-    (set! (ly:music-property result-event-chord 'elements)
-          (cons (make-music 'ArticulationEvent
-                  'articulation-type "marcato")
-                (ly:music-property result-event-chord 'elements)))
-    result-event-chord))
+(define (add-accent note-event)
+  "Add an accent ArticulationEvent to the articulations of `note-event',
+  which is supposed to be a NoteEvent expression."
+  (set! (ly:music-property note-event 'articulations)
+        (cons (make-music 'ArticulationEvent
+                'articulation-type "accent")
+              (ly:music-property note-event 'articulations)))
+  note-event)
 @end example
 
 La primera línea es la forma de definir una función en Scheme: el
 @end example
 
 La primera línea es la forma de definir una función en Scheme: el
-nombre de la función es @code{add-marcato}, y tiene una variable
-llamada @code{event-chord}.  En Scheme, el tipo de variable suele
+nombre de la función es @code{add-accent}, y tiene una variable
+llamada @code{note-event}.  En Scheme, el tipo de variable suele
 quedar claro a partir de su nombre (¡esto también es una buena
 práctica en otros lenguajes de programación!)
 
 @example
 quedar claro a partir de su nombre (¡esto también es una buena
 práctica en otros lenguajes de programación!)
 
 @example
-"Add a marcato..."
+"Add an accent..."
 @end example
 
 @noindent
 @end example
 
 @noindent
@@ -1311,85 +1431,102 @@ es una descripción de lo que hace la función.  No es estrictamente
 necesaria, pero de igual forma que los nombres claros de variable, es
 una buena práctica.
 
 necesaria, pero de igual forma que los nombres claros de variable, es
 una buena práctica.
 
-@example
-(let ((result-event-chord (ly:music-deep-copy event-chord)))
-@end example
-
-Se usa @code{let} para declarar las variables locales.  Aquí usamos
-una variable local, llamada @code{result-event-chord}, a la que le
-damos el valor @code{(ly:music-deep-copy event-chord)}.
-@code{ly:music-deep-copy} es una función específica de LilyPond, como
-todas las funciones que comienzan por @code{ly:}.  Se usa para hacer
-una copia de una expresión musical.  Aquí, copiamos @code{event-chord}
-(el parámetro de la función).  Recuerde que nuestro propósito es
-añadir un marcato a una expresión @code{EventChord}.  Es mejor no
-modificar el @code{EventChord} que se ha dado como argumento, porque
-podría utilizarse en algún otro lugar.
-
-Ahora tenemos un @code{result-event-chord}, que es una expresión
-@code{NoteEventChord} y es una copia de @code{event-chord}.  Añadimos
-el marcato a su propiedad de la lista de @code{'elements}.
+Se preguntará porqué modificamos el evento de nota directamente en
+lugar de trabajar sobre una copia (se puede usar
+@code{ly:music-deep-copy} para ello).  La razón es un contrato
+silencioso: se permite que las funciones musicales modifiquen sus
+argumentos; o bien se generan partiendo de cero (como la entrada del
+usuario) o están ya copiadas (referenciar una variable de música con
+@samp{\name} o la música procedente de expresiones de Scheme
+inmediatas @samp{$(@dots{})} proporcionan una copia).  Dado que sería
+ineficiente crear copias innecesarias, el valor devuelto de una
+función musical @emph{no} se copia.  Así pues, para cumplir dicho
+contrato, no debemos usar ningún argumento más de una vez, y
+devolverlo cuenta como una vez.
+
+En un ejemplo anterior, hemos construido música mediante la repetición
+de un argumento musical dado.  En tal caso, al menos una repetidión
+tuvo que ser una copia de sí misma.  Si no lo fuese, podrían ocurrir
+cosas muy extrañas.  Por ejemplo, si usamos @code{\relative} o
+@code{\transpose} sobre la música resultante que contiene los mismos
+elementos varias veces, estarían sujetos varias veces a la
+relativización o al transporte.  Si los asignamos a una variable de
+música, se rompe el curso porque hacer referencia a @samp{\name}
+creará de nuevo una copia que no retiene la identidad de los elementos
+repetidos.
+
+Ahora bien, aun cuando la función anterior no es una función musical,
+se usará normalmente dentro de funciones musicales.  Así pues, tiene
+sentido obedecer el mismo convenio que usamos para las funciones
+musicales: la entrada puede modificarse para producir la salida, y el
+código que llama es responsable de crear las copias si aún necesita el
+propio argumento sin modificar.  Si observamos las propias funciones
+de LilyPond como @code{music-map}, veremos que se atienen a los mismos
+principios.
+
+¿En qué punto nos encontramos?  Ahora tenemos un @code{note-event} que
+podemos modificar, no a causa de la utilización de
+@code{ly:music-deep-copy} sino por una explicación muy desarrollada.
+Añadimos el acento a su propiedad de lista @code{'articulations}.
 
 @example
 
 @example
-(set! lugar valor-nuevo)
+(set! place new-value)
 @end example
 
 @end example
 
-Aquí, lo que queremos establecer (el @q{lugar}) es la propiedad
-@code{'elements} de la expresión @code{result-event-chord}.
+Aquí, lo que queremos establecer (el @q{place}) es la propiedad
+@code{'articulations} de la expresión @code{note-event}.
 
 @example
 
 @example
-(ly:music-property result-event-chord 'elements)
+(ly:music-property note-event 'articulations)
 @end example
 
 @end example
 
-@code{ly:music-property} es la función que se usa para acceder a las
-propiedades musicales (los @code{'elements}, @code{'duration},
-@code{'pitch}, etc, que vimos en la salida de @code{\displayMusic}
-anterior).  El nuevo valor es la antigua propiedad @code{'elements},
-con un elemento adicional: la expresión @code{ArticulationEvent}, que
-copiamos a partir de la salida de @code{\displayMusic},
+@code{ly:music-property} es la función ustilizada para acceder a las
+propiedades musicales (las @code{'articulations}, @code{'duration},
+@code{'pitch}, etc, que vemos arriba en la salida de
+@code{\displayMusic}).  El nuevo valor es la antigua propiedad
+@code{'articulations}, con un elemento adicional: la expresión
+@code{ArticulationEvent}, que copiamos a partir de la salida de
+@code{\displayMusic},
 
 @example
 (cons (make-music 'ArticulationEvent
 
 @example
 (cons (make-music 'ArticulationEvent
-        'articulation-type "marcato")
-      (ly:music-property result-event-chord 'elements))
+        'articulation-type "accent")
+      (ly:music-property result-event-chord 'articulations))
 @end example
 
 @end example
 
-@code{cons} se usa para añadir un elemento a una lista sin modificar
-la lista original.  Esto es lo que queremos: la misma lista que antes,
-más la expresión @code{ArticulationEvent} nueva.  El orden dentro de
-la propiedad @code{'elements} no es importante aquí.
+Se usa @code{cons} para añadir un elemento a la parte delantera de una
+lista sin modificar la lista original.  Esto es lo que queremos: la
+misma lista de antes, más la nueva expresión @code{ArticulationEvent}.
+El orden dentro de la propiedad @code{'articulations} no tiene
+importancia aquí.
 
 
-Finalmente, una vez hemos añadido la articulación marcato a su
-propiedad @code{elements}, podemos devolver @code{result-event-chord},
-de ahí la última línea de la función.
+Finalmente, una vez hemos añadido la articulación de acento a su
+propiedad @code{articulations}, podemos devolver @code{note-event}, de
+aquí la última línea de la función.
 
 
-Ahora transformamos la función @code{add-marcato} en una función
-musical:
+Ahora transformamos la función @code{add-accent} en una función
+musical (es cuestión de un poco de aderezo sintáctico y una
+declaración del tipo de su único argumento @q{real}).
 
 @example
 
 @example
-addMarcato = #(define-music-function (parser location event-chord)
+addAccent = #(define-music-function (parser location note-event)
                                      (ly:music?)
                                      (ly:music?)
-    "Add a marcato ArticulationEvent to the elements of `event-chord',
-    which is supposed to be an EventChord expression."
-    (let ((result-event-chord (ly:music-deep-copy event-chord)))
-      (set! (ly:music-property result-event-chord 'elements)
-            (cons (make-music 'ArticulationEvent
-                    'articulation-type "marcato")
-                  (ly:music-property result-event-chord 'elements)))
-      result-event-chord))
+  "Add an accent ArticulationEvent to the articulations of `note-event',
+  which is supposed to be a NoteEvent expression."
+  (set! (ly:music-property note-event 'articulations)
+        (cons (make-music 'ArticulationEvent
+                'articulation-type "accent")
+              (ly:music-property note-event 'articulations)))
+  note-event)
 @end example
 
 Podemos verificar que esta función musical funciona correctamente:
 
 @example
 @end example
 
 Podemos verificar que esta función musical funciona correctamente:
 
 @example
-\displayMusic \addMarcato c4
+\displayMusic \addAccent c4
 @end example
 
 
 @end example
 
 
-
-
-
-
 @ignore
 @menu
 * Trucos con Scheme::
 @ignore
 @menu
 * Trucos con Scheme::
@@ -1397,7 +1534,7 @@ Podemos verificar que esta función musical funciona correctamente:
 
 @c @nod e Trucos con Scheme
 @c @sectio n Trucos con Scheme
 
 @c @nod e Trucos con Scheme
 @c @sectio n Trucos con Scheme
-@translationof Tweaking with Scheme
+@c @transl ationof Tweaking with Scheme
 
 Hemos visto cómo la salida de LilyPond se puede modificar
 profundamente usando instrucciones como @code{\override TextScript
 
 Hemos visto cómo la salida de LilyPond se puede modificar
 profundamente usando instrucciones como @code{\override TextScript
@@ -1417,7 +1554,7 @@ TODO Find a simple example
 @lilypond[quote,verbatim,ragged-right]
 padText = #(define-music-function (parser location padding) (number?)
 #{
 @lilypond[quote,verbatim,ragged-right]
 padText = #(define-music-function (parser location padding) (number?)
 #{
-  \once \override TextScript #'padding = #$padding
+  \once \override TextScript #'padding = #padding
 #})
 
 \relative c''' {
 #})
 
 \relative c''' {
@@ -1442,7 +1579,7 @@ tempoPadded = #(define-music-function (parser location padding tempotext)
   (number? string?)
 #{
   \once \override Score.MetronomeMark #'padding = $padding
   (number? string?)
 #{
   \once \override Score.MetronomeMark #'padding = $padding
-  \tempo \markup { \bold $tempotext }
+  \tempo \markup { \bold #tempotext }
 #})
 
 \relative c'' {
 #})
 
 \relative c'' {