drscheme &" and you should see the interpreter/code-entry split window open up. [Note: You have to choose a "language" before you start doing anything. Under the menu: Lanugagues → Choose Language choose PLT → Pretty Big.] The lower pane is the interpreter. You can enter a scheme expression like
(+ 3 4)at the prompt and the
returnkey will cause the interpreter to evaluate the expression - provided the cursor is at the end of the line. You can get the cursor to the end of the line instantly with a ctrl-e combination (control and e keys pressed simultaneously).
sqrt(2.4), in Scheme we say
(sqrt 2.4). Of course, expressions can be nested (composition of functions), so
sqrt(3.4*2.9)is expressed in Scheme as
(sqrt (* 3.4 2.9)).
Section 6.2 of the R5 Scheme language definition describes numbers in Scheme. Here are some high points. Integers in Scheme can be arbitrarily large (BigInts, you'll hear people say), and a number written without a decimal point is given type integer. Floating-point numbers (type "real") are essentially doubles, and if you write a number with a decimal point it'll be treated as a real.. Scheme has built it rational numbers (fractions) and complex numbers as well. We'll concentrate on integers and reals.
All the below functions return integer values.
+ - * quotient remainder modulo max min abs numerator denominator gcd lcm floor ceiling truncate round rationalize exptNotice that division isn't there. Division returns a rational value.
Floating -point functions The above functions that make sense for reals are defined for reals, additionally you have others like:
sin cos tan sqrtwhich ought to be self explanatory.
exact->inexactconverts an exact value (integer or rational) into an inexact (floating-point). Of course if you're clever, you won't need it ...
> (define (f x) (+ (* 2 x x x) (* -1 x x) (* 3 x) -5)) > (f 2.451) 25.793878702This is actually a bit of a shortcut for a function definition, as we'll discuss later. Clearly, you're defineing a new function, whose name is
fand whose parameter names are everything else following in the parentheses (just
xin this case), and then what follows is an expression that is the value of the function. For a simpler example, a function called
my-avemight be defined like this:
(define (my-ave x y) (/ (+ x y) 2.0))Hopefully the three components are clear.
to-fahrenheitthat convert back and forth from Celsius to Fahrenheit. Recall: T_C = 5/9(T_F - 32)
my-distthat takes two arguments, x and y, and computes the distance of point (x,y) from the origin.
test-trigfor sin(x)^2 + x*cos(x).
( if (< x 0) (* -1 x) x )You see, depending on the result of the test, we either get the value -1*x or simply x itself. We can, of course, use this to get define an absolute value function:
(define (my-abs x) (if (< x 0) (* -1 x) x))although, of course, scheme already has one. We can nest these expressions as needed.
The logical operators and, or and not are present in scheme just like you'd suppose. True in scheme is the constant #t and false is the constant #f. For example:
> (and (> 1 0) (< 2 -3)) #f > (or (> 1 0) (< 2 -3)) #tNumbers can be compared with the usual: i.e <, >, ≤, ≥, =. Note: for non-numeric objects the
equal?is what you want to use (also works on numbers).
signed-inc, which returns 1 plus its argument if the argument is non-negative, and -1 plus its argument if the argument is negative.
signed-incso that it returns its argument unchanged if the argument is 0 but otherwise acts as before.
middlethat takes three numbers as argument and returns the middle of the three. E.g.
(middle 4 2 3)should evaluate to 3.
There's also a nice function
cond that's useful
when you have a bunch of distinct cases to consider. For
example, if you want to define a function whats-your-sign
that returns 1,0,-1 according to the sign of a number, you
cond as follows:
(define (whats-your-sign x) (cond ((< x 0) -1) ((> x 0) 1) ((= x 0) 0) ) )So cond's arguments form a list of condition/result pairs. The interpreter finds the first condition that is satisfied, and the value of the cond expression is the result associated with that condition.
middle-old. Then define
middlefrom using cond's and and's.
sum-rangethat would sum all the integers in the given range. Normally we'd think of using loops for this, but Scheme doesn't do loops! They're contrary to the idea of referential transparency - i.e. no side effects. Loops are all about creating side effects - over and over and over. At any rate, we need to use recursion:
(define (sum-range i j) (if (= i j) i (+ i (sum-range (+ i 1) j))))Recursion is nothing new for you folks, you'll just use a lot more of it in Scheme.
factorialfunction. Try taking the factorial of 111. What do you notice about the result. Do you think the straightfoward C++ implementation could've given you this result?
accruethat takes a balance, an annual interest rate, and a number of years and returns the balance at the end of that time period asuming that interest is computed monthly. Recall: If the annual interest rate is r and the balance is B, then one month's compounding produces a new balance of B*(1 + r/1200) (we're assuming a value of, say, 7.5 for r means 7.5%). Hint: A nice bottom-up solution to this would probably involve writing a
(compound-month B r)function, that just does one month of compounding, testing it, and then moving on. Next, write an
accrue-monthsthat would take a balance, a rate, and a number of months, and compute the balance at the end of that many moenths - test it! Then it should be easy to write your
fibto compute Fibonocci numbers. Recall, fib(0) and fib(1) are both 1. All the rest are defined by the rule fib(n) = fib(n-1) + fib(n-2).
letconstruct in Scheme allows you to give a name to a common subexpression. For example, consider the expression
(33 * (501 - 33)) / ( 1 - (33 * (501 - 33)))The natural way to code this in Scheme is probably
(/ (- (* 33 501) 33) (- 1 (- (* 33 501) 33)))But you could say "let a = 33 * (501 - 33), and return a / (1 - a)". That's essentially what
letallows you to do.
(let ((a (- (* 32 501) 33))) (/ a (- 1 a)))Essentially,
letis the Scheme way of getting local variable functionality. What you've got is the
letkeyword, followed by a list of variable-name/value pairs, followed by an expression (presumably using the new names) that provides the value of the whole
letexpression. For example:
> ( let ((a 2) (b 4) (c 6)) (+ a b c) ) 12
letin functions. Suppose I want to define a function called
shifted-cube, which computes (x + 1)^3 for a value x.
> (define (shifted-cube x) (let ((a (+ x 1))) (* a a a))) > (shifted-cube 2) 27
test-sinthat computes 1/(sin(x)^2 + 1) + sqrt(sin(x)^2 + 1) - (sin(x)^2 + 1)^2
distthat computes the difference (in inches) between two lengths (given in feet and inches). Example:
> (diff 3 7 2 11) ← difference between 3' 7'' and 2' 11'' 8Write this function using a
letexpression to create values
L2for the lengths in inches of the input feet-and-inches lengths.