Jump to content

User:Ebe123/GCI-Scheme

From Wikipedia, the free encyclopedia

LilyPond is a programming language for sheet music. It is also very extensible through Scheme, a lisp dialect (in fact it is Scheme with added features to make writing easier). These tasks will be expanding on LilyPond and the Score Extension's primary utility and learning the functional programming paradigm using it. Musical knowledge is not required for these tasks, although music will be involved as a theme of the tasks.

If you get stuck, don't hesitate to contact me, Étienne (Ebe123) on GCI or IRC (#wikimedia-dev connect).

This series of tasks is based on the Scheme tutorials on the LilyPond blog (by Urs Liska and Jean-Marc Legrand).

Task 0: Setting up Score

[edit]

This task does not have any Scheme programming components, rather it is to setup an environment on-wiki in order to complete successive tasks.

  1. On any Wikimedia wiki, create an account and create your user page if not already created stating you are a GCI student. Save the page.
  2. Create a user subpage on that wiki for this series of tasks, stating so in the first edit. Save the page.
  3. Create a new section == Task 0 == with this content:
    <score sound raw>
    \header {
      tagline = ##f
    }
    \score {
      {
        \tempo 4=120
        c4 d e f g a b
      }
      \layout {}
      \midi {}
    }
    </score>
    
    Save.
  4. Notice the magic numbers used. Here, "4" represents the note length defined as a beat, and is used for the "c". "120" has the implicit units of "beats per minute". How long, in seconds, is the piece? Write down the answer (and nothing else). Save.

Task 1: Definitions

[edit]

Scheme is a dialect of Lisp, a functional programming language. It is also what LilyPond is built upon, letting Scheme be mixed with LilyPond to provide more flexibility. Here, we will be taking the LilyPond code from #Task 0 and putting in simple Scheme declarations to learn Scheme keywords.

Please save after completing each number, with the number in the edit summary.

  1. With the code provided in task 0, declare a variable bpm_a to hold the tempo speed as used in task 0. In LilyPond syntax, variables can be defined outside the \score block using <id> = <value>.
  2. These variables can now be accessed with a backslash, then the name of the variable. Change the \tempo declaration to use the bpm_a variable.
  3. Now, lets define another speed but using the Scheme keyword define. Scheme constructs are prefixed in LilyPond by a hashsign (#), and Scheme uses parentheses for blocks of code. define has two arguments, the name to which to assign a value and the value (either a value or anonymous function). Thus, the Scheme function will look like (define <id> <value>). Define a variable bpm_b at half the speed of bpm_a.
  4. A barline is a vertical line that intersects the 5 horizontal lines (the staff) and is bounded by them. Do not confuse them with note stems, which are vertical lines but attached to a specific note (with a note head). Add a tempo declaration after the implicit barline in the LilyPond code, using bpm_b. Scheme definitions can be accessed by prefixing the name by a hashsign.
  5. Write down the length, in seconds, of the whole piece. Don't forget units.
  6. We can also create Scheme functions with embedded LilyPond syntax. Define a LilyPond variable function_a with a Scheme value of (define-music-function (parser location)() ""). define-music-function is a Scheme function defined by LilyPond, which returns LilyPond syntax as it runs. Functional programming does not have return statements. We give the function a few arguments, the parser of the music and the location, which we can ignore.
  7. Replace the empty string by #{ c'4 #}. The #{ block "switches back" to LilyPond syntax within Scheme. This is basically (define function_a #{ c'4 #}). Use function_a after "b" in the score.
  8. What is the length now?