User:Ebe123/GCI-Scheme
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.
- 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.
- Create a user subpage on that wiki for this series of tasks, stating so in the first edit. Save the page.
- 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. - 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.
- 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>
. - These variables can now be accessed with a backslash, then the name of the variable. Change the
\tempo
declaration to use thebpm_a
variable. - 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 variablebpm_b
at half the speed ofbpm_a
. - 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. - Write down the length, in seconds, of the whole piece. Don't forget units.
- 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. - 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. - What is the length now?