410 likes | 468 Views
Introduction to Programming, using Scheme. a.k.a. Bugs, and How to Learn From Them 101 Dinoj Surendran (dinoj@cs, Eckhart basement, Room 2a). Basic Questions . What is programming? Writing down an explicit set of instructions that a machine can follow, usually with a task in mind.
E N D
Introduction to Programming,using Scheme a.k.a. Bugs, and How to Learn From Them 101 Dinoj Surendran (dinoj@cs, Eckhart basement, Room 2a)
Basic Questions • What is programming? • Writing down an explicit set of instructions that a machine can follow, usually with a task in mind. • What is Scheme? • A functional programming language based on Lisp. • How are my grades calculated? • Homework 60%, Midterm 20%, Final 20%. • 16 homeworks at 4% each. • Extra credit for challenge problems. • What’s the course webpage? • http://www.cs.uchicago.edu/~dinoj/2002summer115.html • What are my Office Hours? • Tuesdays and Thursdays 1300 – 1400. I am always accessible by email or via the class mailing list.
More Basic Questions • What text are we using? Where do I get it? • Structure and Interpretation of Computer Programs, Abelson and Sussman2. The book is online, see class webpage. • Can I ask my friends for help with my homework? • No. You can discuss all you want about general concepts, but no more. • Homework suspected to be the product of collaboration receives no credit. Two incidents of this trouble. • How much homework will there be? • Lots. Check the class webpage an hour after class. It is due by 9pm of the day of the next class, and returned to you at the class after that. • What is the late homework policy? • 20% if handed late, but still on the deadline day, and 50% off if handed in the day after that. Excuses for not doing it in time: please tell me 24 hours in advance of the deadline. • What if I can’t finish my homework in time? • Hand it in anyway for partial credit. A short note saying detailing the bug would be good.
Computer Science • A misnomer – by the same token, Biology should be called Microscope Science or Astronomy Telescope Science • We study computation, and computers just happen to be the tools we use. • The purpose of computing is insight, not numbers. -- R. Hamming • Computer scientists study vision, languages, mathematics, hearing, kinematics, neuroscience, physics, etc in addition to compilers, operating systems and the internet • Programming is a basic skill, just as calculus is a basic skill for mathematicians. Mathematicians don’t solve calculus problems all the time, but can do so when they have to.
Programming: Errors • As soon as we started programming, we found to our surprise that it wasn't as easy to get programs right as we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large part of my life from then on was going to be spent in finding mistakes in my own programs. -- Maurice Wilkes, 1949 • There are two ways to write error-free programs; only the third works. -- Alan J. Perlis • I really hate this damned machineI wish that they would sell it.It never does quite what I wantBut only what I tell it. -- A Programmer's Lament
Programming: Erring & Learning • The road to wisdom?Well its plain and simple to express:Err and err and err again, but less and less and less. -- Piet Hein • I, myself, have had many failures and I've learned that if you are not failing a lot, you are probably not being as creative as you could be -you aren't stretching your imagination. -- J. Backus • Learning is never done without errors and defeat. -- Lenin
Programming: Avoiding Errors • The most important single aspect of software development is to be clear about what you are trying to build. -- Bjarne Stroustrup • ...well over half of the time you spend working on a project (on the order of 70 percent) is spent thinking, and no tool, no matter how advanced, can think for you. Consequently, even if a tool did everything except the thinking for you -- if it wrote 100 percent of the code, wrote 100 percent of the documentation, … -- the best you could hope for would be a 30 percent improvement in productivity. In order to do better than that, you have to change the way you think. -- Fred Brook [paraphrased]
Programming: Avoiding Errors II • Haste is of the devil. Slowness is of God. -- H L Mencken • You're bound to be unhappy if you optimize everything. -- Donald Knuth • Programming can be fun, so can cryptography; however they should not be combined. -- Kreitzberg and Shneiderman • Programs must be written for people to read, and only incidentally for machines to execute. -- SICP
General Advice • I hear and I forget; I see and I remember; I do and I understand. -- Anonymous Chinese Proverb • He who asks is a fool for five minutes; he who does not ask remains a fool forever. -- ACP • Never hesitate to ask a lesser person. -- Confucius • The first step in fixing a broken program is getting it to fail repeatedly (on the simplest example possible). -- T. Duff • To arrive at the simple is difficult. -- R. Elisha
Expressions • Everything in Scheme is an expression, and has a value. For example, these are primitives, and are their own value: 5 #\c ‘babalas “braai” 4.122 3+2i #t, #f • The value is sometimes undefined, like (/ 1 0)
Combinations • These are more complicated expressions: (+ 4 1 49) ( sqrt (* 2 8) ) ( string-append “the doh of” “Homer”) (= (/ 18 3) (- 8 2) ) (* 3+3i 4+4i ) • These evaluate to 54, 4, “the doh ofHomer”, #t and 0+24i respectively. • Note the prefix notation! Everything is of the form (function arg1 … argn)
More fun with prefix notation Evaluate (* (/ 4 1) (- 4 2 9) (+ (/ 6 3) (sqrt 9))) • evaluate each argument separately: (/ 4 1) 4/1 = 4 (- 4 2 9) 4-2-9 = -7 (+ (/ 6 3) (sqrt 9) ) (+ 2 3) 5 • then put them together (* 4 –7 5) -140
How Expressions are Evaluated • To evaluate (operator arg1 arg2 … argn) • Evaluate all arguments (RECURSIVE!) • Apply operator to the value of each argument • e.g.(+ (* (- 5 3) (sqrt 9)) (/ (* 20 2) (+ 3 2))) (+ (* 2 3 ) (/ 10 5) (+ 6 2 ) 8
Functions Programming languages like C, Java make a huge distinction between functions and data. Not Scheme. Think of them as ‘pipes’ and ‘balls’, both of which are objects. (lambda (x) (* x 2)) defines a function that doubles its argument (lambda (x y z) (+ x y z) ) defines a function that takes three arguments and returns their sum. (lambda () 0) defines a function that takes no arguments and returns zero. (lamba (x) 0) defines a function taking one argument and returning zero. How to use functions: place them at the start of a compound expression with the correct number of arguments, e.g. ( (lambda (x) (* x 2)) 3 ) 6 ( (lambda (x y z) (+ x y z)) 100 28 4) 132
Parentheses We are used to using parentheses just to make expressions clearer. In Scheme, they have a specific meaning: “What is inside me is a function and its arguments, and I’m going to apply the function to the arguments, and return the result.” Therefore, expressions like (5) or (‘foo 3) are meaningless since 5 and ‘foo are not procedures. Similarly, (+ 3 4) is meaningful, ((+ 3 4)) is not.
Data Abstraction • Make it, name it, forget about it, use it • e.g. Incrementer: -- “make it” (lambda (x) (+ x 1)) -- “name it” (define inc (lambda (x) (+ x 1))) -- “forget about it” – you no longer need to remember how inc was implemented, just know what it does -- “use it” (inc 312) 313 • both data and functions can be abstracted, e.g. (define quayle-iq 50) means that you can say (inc quayle-iq) and receive 51
Why is Data Abstraction a Good Thing? • Don’t need to know how something is implemented in order to use it – imagine a world where you needed to know how your car worked to get your driver’s license (it would be a world with a lot of illegal drivers). • Can change the implementation of something without changing the way it is used – your car engine can be replaced with a new one without you having to change the way you drive your car. • Code reuse – you don’t have to implement everything from scratch – if you know you need new brakes, and know the specs used by your car, you can get them from someone else without having to make them yourself.
Example 1.1 • A function that returns the circumference of a circle, when given its radius • (define pi 3.14159) • (define circum (lambda (r) (* 2 r pi)) ) • Alternatively (define (circum x) (* 2 x pi) ) • Note how name of parameter (x or r) is irrelevant • Usage: (circum 5) 31.4159
Example 1.2 • Function which greets when you give it a name • (define hello (lambda (name) (string-append “hello ” name “ you slimy worm”) ) ) • (define (hello name) (string-append “hello ” name “ you slimy worm”) ) • Usage: (hello “don”) “hello don you slimy worm”
Example 1.3 • (define (piggy x) (* 2 x) ) • (define (gonzo x y) (- x y) ) • (define (bunsen x y) (/ x y) ) • (define (kermit x y) (bunsen (piggy x) (gonzo x y) ) ) Usage: (gonzo 100 2) 98 (bunsen 100 0) “aaargh!!” (piggy (bunsen 6 2)) (piggy 3) 6 (kermit 5 2) (bunsen (piggy 5) (gonzo 5 2) ) (bunsen 10 3) 10/3
The Substitution Model • How expressions are evaluated • If the expression is a primitive, it is its own value • If it is a compound expression -- not a special form -- like (function arg1 … argn), then • Evaluate function, arg1, … argn • Apply function to arguments, by replacing the parameters in the body of the function definition with the arguments, and then evaluating this
Example 1.4(Substitution Model) • (define piggy (lambda (x) (* 2 x)) ) • (define gonzo (lambda (x y) (- x y)) ) • Evaluate (piggy (gonzo 3 5)) -- evaluate piggy: (lambda (x) (* 2 x)) -- evaluate (gonzo 3 5) -- evaluate gonzo: (lambda (x y) (- x y) ) -- evaluate 3 5: these are primitives so are themselves. -- apply (lambda (x y) (- x y)) to 3 5: eval (- 3 5) -2 -- (gonzo 3 5) has been evaluated to get –2 -- apply (lambda (x) (* 2 x)) to –2: eval (* 2 –2) -4
Substitution Model : fine print • This is an idealized version of how things work • EXCEPTION: If the function is AND or OR, and the first argument evaluates to #f or #t respectively, the second argument is not evaluated. • Therefore (or (= 2 2) (/ 1 0) ) will not produce an error since (/ 1 0) will not be evaluated • Suppose we defined our own OR function (define myor (lambda (x y) (or x y)) ) (define (myor x y) (or x y) ) • (myor (= 2 2) (/ 1 0))will produce an error. WHY?
Conditional Statements • The general form of a conditional: (cond (<p1> <e1>) (<p2> <e2>) ... (<pn> <en>) ) • For example, this function returns the max of a,b (lambda (a b) (cond ( (> a b) a) ( (< a b) b) ( (= a b) a) ) )
Conditional Statements (else) • For convenience, the last condition can be “else”, which covers every other condition (lambda (a b) (cond ((> a b) a) ( else b) ) )
Conditional Statements (if) • A common occurrence is that there are only two conditions: (if condition dothis dothat) • For example (lambda (a b) (if (> a b) a b) ) (lambda (x) ( (if (> x 0) + -) x) ) implement the MAX and ABS function
Example 1.5 • The IF statement can be replaced by the COND statement. (define (myif condition dothis dothat) (cond (condition dothis) (else dothat) ) )
Example 1.5 • Consider the following function to return (sin x)/x (define (lambda x) (myif (= x 0) 1 (/ (sin x) x) ) ) • This crashes when given the input x=0. • The same function, with MYIF replaced by IF, does not crash. WHY? • Moral: IF can be replaced by COND, but only internally.
Example 1.6 • Define a procedure that displays the roots of ax2+bx+c = 0. If there are no roots, it displays “no roots”. You can assume a is nonzero. • Solution: • calculate b2-4ac • If this is negative, display “no roots” • Otherwise, display (-b +/- sqrt(b2-4ac) ) / 2a
Example 1.6 • (define (discrim a b c) (- (* b b) (* 4 a c) ) ) • (define (solvequadratic a b c) ; assumes a nonzero (if (< (discrim a b c) 0) (begin (display “no roots”) (newline) ) (begin (display (/ (+ (- b) (sqrt (discrim a b c))) (* 2 a))) (newline) (display (/ (- (- b) (sqrt (discrim a b c))) (* 2 a))) (newline) ) ) )
Example 1.6 • (define (solvequadratic a b c) (define (discrim a b c) (- (* b b) (* 4 a c) ) ) (if (< (discrim a b c) 0) (begin (display “no roots”) (newline) ) (begin (display (/ (+ (- b) (sqrt (discrim a b c))) (* 2 a))) (newline) (display (/ (- (- b) (sqrt (discrim a b c))) (* 2 a))) (newline) ) ) )
Example 1.6 • (define (solvequadratic a b c) (define discrim (- (* b b) (* 4 a c) ) ) (if (< discrim 0) (begin (display “no roots”) (newline) ) (begin (display (/ (+ (- b) (sqrt discrim)) (* 2 a))) (newline) (display (/ (- (- b) (sqrt discrim)) (* 2 a))) (newline) ) ) )
Example 1.6 • Improved solution: store intermediate variables. (More on the LET statement in future lectures.) (define (solvequadratic a b c) (define discrim (- (* b b) (* 4 a c) ) ) (if (< discrim 0) (begin (display "no roots") (newline) ) (let* ((denom (* 2 a)) (part1 (/ (- b) denom) ) (part2 (/ (sqrt discrim) denom) )) (begin (display (- part1 part2) ) (newline) (display (+ part1 part2) ) (newline) ))))
Example 1.7 • Rewrite previous example so that it deals with all possible cases of a, b, c. (define (solvegeneralquad a b c) (if (= a 0) (if (= b 0) (if (= c 0) (begin (display "any x is solution") (newline) ) (begin (display "no solutions") (newline) ) ) (begin (display (/ (- c) b) ) (newline) ) ) (solvequadratic a b c) ) )
Example 1.8 Finding square roots with Newton’s Method: begin x:= 1 while x not close enough to sqrt(A) x = ½ (x + A/x) end x A/x ½(x + A/x) 1 2/1 = 2 ½ (2 + 1) = 1.5 1.5 2/1.5 = 1.3333 ½ (1.3333 + 1.5) =1.4167 1.4167 2/1.4167 = 1.4118 ½ (1.4167 + 1.4118) =1.4142
Example 1.8 Implementing a procedure like this will become standard to you. For now, you have to think a bit. The basic idea is to keep trying new guesses: (define (trythis x A) (if (goodenough x A) x (trythis (newguess x A) A) ) ) You now need to figure out what (goodenough x A) and (newguess x A) should be.
Example 1.8 The algorithm clearly states how we should find a new guess given the previous guess: (define (newguess x A) (/ (+ x (/ A x)) 2) ) An unsophisticated way of deciding whether a guess x is good enough is checking if |x2 – A| < 0.001 (define (goodenough x A) (< (abs (- (* x x) A)) 0.001) )
Example 1.8 We have now defined three separate parts of our program: (define (trythis x A) (if (goodenough x A) x (trythis (newguess x A) A))) (define (newguess x A) (/ (+ x (/ A x)) 2) ) (define (goodenough x A) (< (abs (- (* x x) A)) 0.001) ) How do we put all this together? We need to make the call (trythis 1 A).
Example 1.8 (define (NewtonRoot A) (define (trythis x A) (if (goodenough x A) x (trythis (newguess x A) A))) (define (newguess x A) (/ (+ x (/ A x)) 2) ) (define (goodenough x A) (< (abs (- (* x x) A)) 0.001) ) (trythis 1.0 A) )
Summary • Computer Science isn’t all about programming • Programming is all about making errors and learning from them. And also about thinking. • In Scheme, every expression has a value. • Parentheses mean (evaluate me). • Scheme makes no distinction between functions and data. • Functions are defined using lambda. • The Substitution Model gives an idea as to how Scheme evaluates expressions. • Data abstraction means naming data and functions and then using them via these names • Conditional statements are implemented using if and cond.