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
return key 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)).
Numeric Types
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.
Integer functions
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.
Exercises:
exact->inexact converts 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
f and whose parameter
names are everything else following in the parentheses (just
x in this case), and then what follows is
an expression that is the value of the function. For a
simpler example, a function called my-ave
might be defined like this:
(define (my-ave x y) (/ (+ x y) 2.0))Hopefully the three components are clear.
Exercises
to-celsius and
to-fahrenheit that convert back and forth
from Celsius to Fahrenheit. Recall: T_C = 5/9(T_F - 32)
my-dist that takes two
arguments, x and y, and
computes the distance of point (x,y) from the origin.test-trig for 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).
Exercises:
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-inc so that it returns its
argument unchanged if the argument is 0 but otherwise acts
as before.middle that 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
miught use 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.
Exercises:
middle function to middle-old. Then define middle from using cond's
and and's.sum-range that 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.
Exercises:
factorial function. 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?accrue that 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-months that 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 accrue function.
fib to 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).
let construct 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
let allows you to do.
(let ((a (- (* 32 501) 33))) (/ a (- 1 a)))Essentially,
let is the Scheme way of getting local
variable functionality. What you've got is the
let keyword, 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 let expression. For example:
> ( let ((a 2) (b 4) (c 6)) (+ a b c) ) 12
let in functionslet in 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
Exercises:
test-sin that computes
1/(sin(x)^2 + 1) + sqrt(sin(x)^2 + 1) - (sin(x)^2 + 1)^2
dist that 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''
8
Write this function using a let expression
to create values L1 and L2 for
the lengths in inches of the input feet-and-inches lengths.