# Funciones

Cuando comiences a escribir mucho código, desearás encontrar una manera de organizar y estructurar todo para hacerlo más entendible. Las funciones permiten hacer exactamente eso, permitiéndonos darle nombre a muchas partes de nuestro código. Veamos:

## Definiendo Funciones

    define :foo do
      play 50
      sleep 1
      play 55
      sleep 2
    end

Aquí definimos una nueva función llamada `foo`. Lo hacemos con nuestro viejo amigo el bloque de do/end y la palabra mágica `define` seguidos del nombre que queremos darle a nuestra función. No necesitábamos llamarla `foo`, podríamos haberla llamado cualquier cosa que quisiésemos, tales como `bar`, `baz` o idealmente algo significativo para tí como `main_section` o `lead_riff`.

Recuerda anteponer dos puntos `:` al nombre de la función que defines.

## Llamando las Funciones

Una vez hemos definido nuestra función, podemos llamarla simplemente escribiendo su nombre:

    define :foo do
      play 50
      sleep 1
      play 55
      sleep 0.5
    end

    foo

    sleep 1

    2.times do
      foo
    end

Incluso podemos usar `foo` dentro de bloques de iteración o cualquier lugar donde hayamos escrito `play` o `sample`. Esto nos da una fantástica manera de expresar y crear nuevas palabras significativas a usar en nuestras composiciones.

## Las funciones permanecen en memoria

Hasta ahora, cada vez que presionamos el botón de Ejecutar, Sonic Pi ha comenzado de cero. Sólo conoce lo que está en el buffer actual. No puedes referenciar código en otro buffer o hilo. sin embargo, las funciones cambian eso. Cuando defines una función, Sonic Pi recuerda. Probemos borrando todo el código en tu buffer y reemplazandolo por:

    foo

Presiona el botón de Ejecutar y escucha. ¿Dónde se fue el código?¿cómo supo Sonic Pi qué tocar? Sonic Pi recordó tu función, inclusive cuando la borraste del buffer. Esta conducta sólo funciona con las funciones creadas con `define` (y `defonce`).

## Funciones parametrizadas

Quizás te interese saber que al igual que podías pasar valores mínimos y máximos con `rrand`, también puedes enseñar a tus funciones a aceptar argumentos. Miremos:

    define :my_player do |n|
      play n
    end

    my_player 80
    sleep 0.5
    my_player 90

Esto no es tan excitante, pero ilustra el punto. Creamos nuestra propia versión de `play` llamada `my_player` y la cual está parametrizada.

Los parámetros deben ir después del `do` y `define` en el bloque `do/end`, rodeado de postes verticales `|` y separados por comas `,`. Puedes usar cualquier palabra para los nombres de los parámetros.

Lo mágico sucede dentro del bloque do/end del `define` . Puedes usar nombres de parámetros como si fueran valores reales. En este ejemplo estoy tocando la nota `n`. Puedes considerar los parámetros como una especie de promesa de que cuando el código se ejecute, ellos serán reemplazados por los valores. Esto lo haces al pasar un parámetro a la función, cuando la llamas. Yo lo hago con `my_player 80` para tocar la nota 80. Dentro de la definición de la función `n` se reemplaza con 80, así `play n` se convierte en `play 80`. Cuando la llamo otra vez con `my_player 90`, `n` es reemplazada por 90, así que `play n` se convierte en `play 90`.

Veamos un ejemplo más interesante:

    define :chord_player do |root, repeats|
      repeats.times do
        play chord(root, :minor), release: 0.3
        sleep 0.5
      end
    end

    chord_player :e3, 2
    sleep 0.5
    chord_player :a3, 3
    chord_player :g3, 4
    sleep 0.5
    chord_player :e3, 3

Aquí usé `repeats` como si fuera un número para la línea de `repeats.times do`. También usé `root` como si fuera un nombre de nota en mi llamada a `play`.

¡Nota cómo podemos utilizar algo muy expresivo y fácil de leer sólo con mover mucho de nuestra lógica en el código!