12 A Gentle Introduction to muSE
muSE stands for muvee Symbolic Expressions - a scripting language used in the specification of muvee Reveal’s styles. A style package’s data.scm file is a muSE script that decides what the various aspects of a style should be.
This document introduces muSE to those who are may not be familiar with it or the language Scheme on which it is based. It is intended to be a gentle as well as a quick introduction to the underlying scripting language.
For detailed information about muSE, see its project page.
We strongly recommend that you use the DrScheme program to view and edit muSE files. You can use DrScheme to try out the expressions that we present in this quick tutorial.
12.1 Expressions
A muSE data file typically ends with the extension .scm for “Scheme”. However, we like to call them “scum” files. A scm file consists of a sequence of muSE expressions which are evaluated in the order in which they appear.
simple decimal numbers : 1, 2, -15, 355, 113, etc.
fractional numbers : 1.2, 3.1415, -100.0, etc.
hexadecimal numbers : 0xbabe, 0xF00D, etc.
strings : "Hello muSE", "Louis sang 'What a wonderful world!'", etc.
symbols : mumboJumbo, MuveeTechnologies, nuclear-cockroach, dont-sw^%$#-in-code?, etc. Symbols start with a letter and can contain any character other than quotes, brackets, and period.
- lists : A list of items is notated within parentheses. For example -
(1 2 3 4 5)
(1 "He" 2 "HeHee" 3 "HeHeHeee")
(Name "Willy Wonka" Age 30 Height 5.8)
Lists can consist of simple data such as shown above or consist of other lists. Here is an example of a list that mixes them up -("List demo" 1 2.34 five (Name "Willy Wonka") (Age 30) (Height 5.8))
12.2 Evaluating an expression
Simple data values such as numbers and strings evaluate to themselves - i.e. 3.1415, when it occurs anywhere, always means the same value 3.1415
- Symbols may be defined to other values using the (define ...) form like this -
(define Name "Willy Wonka")
After evaluating the above definition, the symbol Name by itself will be replaced by the string "Willy Wonka" (without the double quotation marks).
12.2.1 List expressions
The first item in the list is evaluated to determine an operator
The operator is then applied to the rest of the list in order to derive the value of the expression.
(+ 1 2 3 4)
(1 2 3 4)
10
So the value of the expression (+ 1 2 3 4) is 10.
(/ (- 100 30) (+ 100 30))
(/ (- 100 30) (+ 100 30)) (/ 70 (+ 100 30)) (/ 70 130) 0.538462
muSE includes a host of built-in operators that perform various computations on their operands. It also includes facilities to define your own operators within muSE itself (see [#Functions] below).
12.2.2 Quoted expressions
'(+ 1 2 3 4)
Literally the list of items +,1,2,3,and 4.0
'pie
(define pie 3.141592654)
Hence, you use the quoting to escape evaluation.
12.3 Functions
(/ (- 100 30) (+ 100 30)) (/ (- 10 5) (+ 10 5)) (/ (- 31 7) (+ 31 7)) (/ (- 355 113) (+ 355 113))
(/ (- a b) (+ a b))
(fn (a b) (/ (- a b) (+ a b)))
(define f (fn (a b) (/ (- a b) (+ a b))))
(f 100 30) (f 10 5) (f 31 7) (f 355 113)
* Note that we use the terms function and operator interchangeably.
(f 31 7)
(a b)
(31 7)
(/ (- 31 7) (+ 31 7))
12.4 Applying operators to operands
If the operands to be passed to an operator are available as the value of another symbol and not explicitly at the time of writing the expression, the operator can be applied using the apply operator. This is possible because operators (aka functions) themselves are values that can be operands to other higher order operators.
(define one-to-ten '(1 2 3 4 5 6 7 8 9 10))
(+ 1 2 3 4 5 6 7 8 9 10)
(apply + one-to-ten)
(eval x) = (apply (eval (first x)) (map eval (rest x)))
(apply + one-to-ten) (apply + '(1 2 3 4 5 6 7 8 9 10)) (eval '(+ 1 2 3 4 5 6 7 8 9 10)) (+ 1 2 3 4 5 6 7 8 9 10) 55
12.5 Truth and falsehood
(> 3 2) (< 30 13) (>= 5.3 3.5) (and (>= 5.3 3.5) (< 314 355)) (or (= 2 3) (= 3 2))
The symbol T is commonly used by such comparison operators to represent truth.
12.6 Conditional evaluation
12.6.1 if
(if condition yes-value no-value)
(if (< 2 3) "muSE knows numbers" "muSE doesn't know numbers")
(define f (fn (a b) (/ (if (< a b) (- b a) (- a b)) (+ a b))))
(if (< a b) (- b a) (- a b))
Notice how we’re using the fact that if expressions evaluates to a single value and is not a control statement like in other languages.
12.6.2 case
(case N (1 "one") (2 "two") (3 "three"))
12.7 Temporary names using let
(if (< a b) (- b a) (- a b))
(fn (a b) (let ((difference (if (< a b) (- b a) (- a b))) (sum (+ a b))) (/ difference sum)))
(let ((name1 value1) (name2 value2) .... (nameN valueN)) expression)
12.8 Recursive functions
The term recursion is used to talk about ways to inductively specify a computation on some data in terms of a computation on a subset of the data. (That’s a simplified view, but it is sufficient for introductory purposes.)
To calculate the sum of numbers from m to n, you add m to the sum of numbers from m + 1 to n, unless m is greater than n, in which case the sum is taken to be 0.
(define (sum-of-numbers m n) (if (> m n) 0 (+ m (sum-of-numbers (+ m 1) n))))
You can also define two functions in terms of each other. In such a case, the functions are said to be mutually recursive. For example, the even and odd functions below are defined mutually recursively.
(define (even n)) ; Declare even function (define (odd n)) ; Declare odd function (define (even n) (if (= n 0) 'yes (odd (- n 1)))) (define (odd n) (if (= n 0) 'no (even (- n 1))))
The above code says “ a number is even if its predecessor is odd and a number is odd if its predecessor is even”. The definitions work for all n >= 0.